From 5683f076331d2831eb4720b65bb53e8d01ca33ee Mon Sep 17 00:00:00 2001 From: Einar Johan Trøan Sømåen Date: Sat, 21 Jul 2012 18:19:07 +0200 Subject: WINTERMUTE: Rename CamelCased filenames to prefixed_under_score-filenames This is mostly a lead-up to namespacing the Ad/Base folders, and then possibly removing the prefixes from the files, it also has the added benefit of getting rid of the odd case-typos that makes for issues on platforms that don't ignore case. --- engines/wintermute/ad/AdActor.cpp | 1316 ------ engines/wintermute/ad/AdActor.h | 107 - engines/wintermute/ad/AdEntity.cpp | 1027 ----- engines/wintermute/ad/AdEntity.h | 68 - engines/wintermute/ad/AdGame.cpp | 2061 --------- engines/wintermute/ad/AdGame.h | 161 - engines/wintermute/ad/AdInventory.cpp | 119 - engines/wintermute/ad/AdInventory.h | 52 - engines/wintermute/ad/AdInventoryBox.cpp | 372 -- engines/wintermute/ad/AdInventoryBox.h | 64 - engines/wintermute/ad/AdItem.cpp | 760 ---- engines/wintermute/ad/AdItem.h | 70 - engines/wintermute/ad/AdLayer.cpp | 537 --- engines/wintermute/ad/AdLayer.h | 58 - engines/wintermute/ad/AdNodeState.cpp | 169 - engines/wintermute/ad/AdNodeState.h | 58 - engines/wintermute/ad/AdObject.cpp | 1203 ------ engines/wintermute/ad/AdObject.h | 123 - engines/wintermute/ad/AdPath.cpp | 112 - engines/wintermute/ad/AdPath.h | 56 - engines/wintermute/ad/AdPathPoint.cpp | 75 - engines/wintermute/ad/AdPathPoint.h | 50 - engines/wintermute/ad/AdRegion.cpp | 392 -- engines/wintermute/ad/AdRegion.h | 58 - engines/wintermute/ad/AdResponse.cpp | 143 - engines/wintermute/ad/AdResponse.h | 61 - engines/wintermute/ad/AdResponseBox.cpp | 647 --- engines/wintermute/ad/AdResponseBox.h | 87 - engines/wintermute/ad/AdResponseContext.cpp | 70 - engines/wintermute/ad/AdResponseContext.h | 50 - engines/wintermute/ad/AdRotLevel.cpp | 159 - engines/wintermute/ad/AdRotLevel.h | 49 - engines/wintermute/ad/AdScaleLevel.cpp | 157 - engines/wintermute/ad/AdScaleLevel.h | 50 - engines/wintermute/ad/AdScene.cpp | 2752 ------------ engines/wintermute/ad/AdScene.h | 181 - engines/wintermute/ad/AdSceneNode.cpp | 83 - engines/wintermute/ad/AdSceneNode.h | 54 - engines/wintermute/ad/AdSceneState.cpp | 88 - engines/wintermute/ad/AdSceneState.h | 51 - engines/wintermute/ad/AdSentence.cpp | 317 -- engines/wintermute/ad/AdSentence.h | 85 - engines/wintermute/ad/AdSpriteSet.cpp | 312 -- engines/wintermute/ad/AdSpriteSet.h | 54 - engines/wintermute/ad/AdTalkDef.cpp | 260 -- engines/wintermute/ad/AdTalkDef.h | 58 - engines/wintermute/ad/AdTalkHolder.cpp | 366 -- engines/wintermute/ad/AdTalkHolder.h | 57 - engines/wintermute/ad/AdTalkNode.cpp | 266 -- engines/wintermute/ad/AdTalkNode.h | 63 - engines/wintermute/ad/AdTypes.h | 107 - engines/wintermute/ad/AdWaypointGroup.cpp | 261 -- engines/wintermute/ad/AdWaypointGroup.h | 58 - engines/wintermute/ad/ad_actor.cpp | 1316 ++++++ engines/wintermute/ad/ad_actor.h | 107 + engines/wintermute/ad/ad_entity.cpp | 1027 +++++ engines/wintermute/ad/ad_entity.h | 68 + engines/wintermute/ad/ad_game.cpp | 2061 +++++++++ engines/wintermute/ad/ad_game.h | 161 + engines/wintermute/ad/ad_inventory.cpp | 119 + engines/wintermute/ad/ad_inventory.h | 52 + engines/wintermute/ad/ad_inventory_box.cpp | 372 ++ engines/wintermute/ad/ad_inventory_box.h | 64 + engines/wintermute/ad/ad_item.cpp | 760 ++++ engines/wintermute/ad/ad_item.h | 70 + engines/wintermute/ad/ad_layer.cpp | 537 +++ engines/wintermute/ad/ad_layer.h | 58 + engines/wintermute/ad/ad_node_state.cpp | 169 + engines/wintermute/ad/ad_node_state.h | 58 + engines/wintermute/ad/ad_object.cpp | 1203 ++++++ engines/wintermute/ad/ad_object.h | 123 + engines/wintermute/ad/ad_path.cpp | 112 + engines/wintermute/ad/ad_path.h | 56 + engines/wintermute/ad/ad_path_point.cpp | 75 + engines/wintermute/ad/ad_path_point.h | 50 + engines/wintermute/ad/ad_region.cpp | 392 ++ engines/wintermute/ad/ad_region.h | 58 + engines/wintermute/ad/ad_response.cpp | 143 + engines/wintermute/ad/ad_response.h | 61 + engines/wintermute/ad/ad_response_box.cpp | 647 +++ engines/wintermute/ad/ad_response_box.h | 87 + engines/wintermute/ad/ad_response_context.cpp | 70 + engines/wintermute/ad/ad_response_context.h | 50 + engines/wintermute/ad/ad_rot_level.cpp | 159 + engines/wintermute/ad/ad_rot_level.h | 49 + engines/wintermute/ad/ad_scale_level.cpp | 157 + engines/wintermute/ad/ad_scale_level.h | 50 + engines/wintermute/ad/ad_scene.cpp | 2752 ++++++++++++ engines/wintermute/ad/ad_scene.h | 181 + engines/wintermute/ad/ad_scene_node.cpp | 83 + engines/wintermute/ad/ad_scene_node.h | 54 + engines/wintermute/ad/ad_scene_state.cpp | 88 + engines/wintermute/ad/ad_scene_state.h | 51 + engines/wintermute/ad/ad_sentence.cpp | 317 ++ engines/wintermute/ad/ad_sentence.h | 85 + engines/wintermute/ad/ad_sprite_set.cpp | 312 ++ engines/wintermute/ad/ad_sprite_set.h | 54 + engines/wintermute/ad/ad_talk_def.cpp | 260 ++ engines/wintermute/ad/ad_talk_def.h | 58 + engines/wintermute/ad/ad_talk_holder.cpp | 366 ++ engines/wintermute/ad/ad_talk_holder.h | 57 + engines/wintermute/ad/ad_talk_node.cpp | 266 ++ engines/wintermute/ad/ad_talk_node.h | 63 + engines/wintermute/ad/ad_types.h | 107 + engines/wintermute/ad/ad_waypoint_group.cpp | 261 ++ engines/wintermute/ad/ad_waypoint_group.h | 58 + engines/wintermute/base/BActiveRect.cpp | 107 - engines/wintermute/base/BActiveRect.h | 60 - engines/wintermute/base/BBase.cpp | 178 - engines/wintermute/base/BBase.h | 64 - engines/wintermute/base/BDebugger.cpp | 203 - engines/wintermute/base/BDebugger.h | 95 - engines/wintermute/base/BDynBuffer.cpp | 192 - engines/wintermute/base/BDynBuffer.h | 66 - engines/wintermute/base/BFader.cpp | 176 - engines/wintermute/base/BFader.h | 62 - engines/wintermute/base/BFileManager.cpp | 737 ---- engines/wintermute/base/BFileManager.h | 85 - engines/wintermute/base/BFrame.cpp | 705 --- engines/wintermute/base/BFrame.h | 73 - engines/wintermute/base/BGame.cpp | 4478 -------------------- engines/wintermute/base/BGame.h | 391 -- engines/wintermute/base/BKeyboardState.cpp | 304 -- engines/wintermute/base/BKeyboardState.h | 75 - engines/wintermute/base/BNamedObject.cpp | 65 - engines/wintermute/base/BNamedObject.h | 50 - engines/wintermute/base/BObject.cpp | 1128 ----- engines/wintermute/base/BObject.h | 144 - engines/wintermute/base/BParser.cpp | 436 -- engines/wintermute/base/BParser.h | 89 - engines/wintermute/base/BPersistMgr.cpp | 778 ---- engines/wintermute/base/BPersistMgr.h | 114 - engines/wintermute/base/BPoint.cpp | 64 - engines/wintermute/base/BPoint.h | 50 - engines/wintermute/base/BQuickMsg.cpp | 54 - engines/wintermute/base/BQuickMsg.h | 48 - engines/wintermute/base/BRegion.cpp | 508 --- engines/wintermute/base/BRegion.h | 68 - engines/wintermute/base/BRegistry.cpp | 257 -- engines/wintermute/base/BRegistry.h | 76 - engines/wintermute/base/BResources.cpp | 2820 ------------ engines/wintermute/base/BResources.h | 44 - engines/wintermute/base/BSaveThumbHelper.cpp | 79 - engines/wintermute/base/BSaveThumbHelper.h | 50 - engines/wintermute/base/BScriptHolder.cpp | 473 --- engines/wintermute/base/BScriptHolder.h | 74 - engines/wintermute/base/BScriptable.cpp | 188 - engines/wintermute/base/BScriptable.h | 90 - engines/wintermute/base/BSound.cpp | 288 -- engines/wintermute/base/BSound.h | 88 - engines/wintermute/base/BSoundBuffer.cpp | 383 -- engines/wintermute/base/BSoundBuffer.h | 100 - engines/wintermute/base/BSoundMgr.cpp | 292 -- engines/wintermute/base/BSoundMgr.h | 69 - engines/wintermute/base/BSprite.cpp | 758 ---- engines/wintermute/base/BSprite.h | 90 - engines/wintermute/base/BStringTable.cpp | 229 - engines/wintermute/base/BStringTable.h | 55 - engines/wintermute/base/BSubFrame.cpp | 589 --- engines/wintermute/base/BSubFrame.h | 86 - engines/wintermute/base/BSurfaceStorage.cpp | 189 - engines/wintermute/base/BSurfaceStorage.h | 57 - engines/wintermute/base/BTransitionMgr.cpp | 131 - engines/wintermute/base/BTransitionMgr.h | 54 - engines/wintermute/base/BViewport.cpp | 98 - engines/wintermute/base/BViewport.h | 55 - engines/wintermute/base/base.cpp | 178 + engines/wintermute/base/base.h | 64 + engines/wintermute/base/base_active_rect.cpp | 107 + engines/wintermute/base/base_active_rect.h | 60 + engines/wintermute/base/base_debugger.cpp | 203 + engines/wintermute/base/base_debugger.h | 95 + engines/wintermute/base/base_dynamic_buffer.cpp | 192 + engines/wintermute/base/base_dynamic_buffer.h | 66 + engines/wintermute/base/base_fader.cpp | 176 + engines/wintermute/base/base_fader.h | 62 + engines/wintermute/base/base_file_manager.cpp | 737 ++++ engines/wintermute/base/base_file_manager.h | 85 + engines/wintermute/base/base_frame.cpp | 705 +++ engines/wintermute/base/base_frame.h | 73 + engines/wintermute/base/base_game.cpp | 4477 +++++++++++++++++++ engines/wintermute/base/base_game.h | 391 ++ engines/wintermute/base/base_keyboard_state.cpp | 304 ++ engines/wintermute/base/base_keyboard_state.h | 75 + engines/wintermute/base/base_named_object.cpp | 65 + engines/wintermute/base/base_named_object.h | 50 + engines/wintermute/base/base_object.cpp | 1128 +++++ engines/wintermute/base/base_object.h | 144 + engines/wintermute/base/base_parser.cpp | 436 ++ engines/wintermute/base/base_parser.h | 89 + .../wintermute/base/base_persistence_manager.cpp | 778 ++++ engines/wintermute/base/base_persistence_manager.h | 114 + engines/wintermute/base/base_point.cpp | 64 + engines/wintermute/base/base_point.h | 50 + engines/wintermute/base/base_quick_msg.cpp | 54 + engines/wintermute/base/base_quick_msg.h | 48 + engines/wintermute/base/base_region.cpp | 508 +++ engines/wintermute/base/base_region.h | 68 + engines/wintermute/base/base_registry.cpp | 257 ++ engines/wintermute/base/base_registry.h | 76 + engines/wintermute/base/base_save_thumb_helper.cpp | 79 + engines/wintermute/base/base_save_thumb_helper.h | 50 + engines/wintermute/base/base_script_holder.cpp | 473 +++ engines/wintermute/base/base_script_holder.h | 74 + engines/wintermute/base/base_scriptable.cpp | 188 + engines/wintermute/base/base_scriptable.h | 90 + engines/wintermute/base/base_sprite.cpp | 758 ++++ engines/wintermute/base/base_sprite.h | 90 + engines/wintermute/base/base_string_table.cpp | 229 + engines/wintermute/base/base_string_table.h | 55 + engines/wintermute/base/base_sub_frame.cpp | 589 +++ engines/wintermute/base/base_sub_frame.h | 86 + engines/wintermute/base/base_surface_storage.cpp | 189 + engines/wintermute/base/base_surface_storage.h | 57 + .../wintermute/base/base_transition_manager.cpp | 131 + engines/wintermute/base/base_transition_manager.h | 54 + engines/wintermute/base/base_viewport.cpp | 98 + engines/wintermute/base/base_viewport.h | 55 + engines/wintermute/base/file/BDiskFile.cpp | 131 - engines/wintermute/base/file/BDiskFile.h | 42 - engines/wintermute/base/file/BFile.cpp | 69 - engines/wintermute/base/file/BFile.h | 67 - engines/wintermute/base/file/BFileEntry.cpp | 50 - engines/wintermute/base/file/BFileEntry.h | 57 - engines/wintermute/base/file/BPackage.cpp | 104 - engines/wintermute/base/file/BPackage.h | 61 - engines/wintermute/base/file/BPkgFile.cpp | 6 +- engines/wintermute/base/file/BPkgFile.h | 5 +- engines/wintermute/base/file/BSaveThumbFile.cpp | 146 - engines/wintermute/base/file/BSaveThumbFile.h | 52 - engines/wintermute/base/file/base_disk_file.cpp | 131 + engines/wintermute/base/file/base_disk_file.h | 42 + engines/wintermute/base/file/base_file.cpp | 69 + engines/wintermute/base/file/base_file.h | 67 + engines/wintermute/base/file/base_file_entry.cpp | 50 + engines/wintermute/base/file/base_file_entry.h | 57 + engines/wintermute/base/file/base_package.cpp | 104 + engines/wintermute/base/file/base_package.h | 61 + engines/wintermute/base/file/base_resources.cpp | 2820 ++++++++++++ engines/wintermute/base/file/base_resources.h | 44 + .../wintermute/base/file/base_save_thumb_file.cpp | 146 + .../wintermute/base/file/base_save_thumb_file.h | 52 + engines/wintermute/base/font/BFont.cpp | 206 - engines/wintermute/base/font/BFont.h | 61 - engines/wintermute/base/font/BFontBitmap.cpp | 540 --- engines/wintermute/base/font/BFontBitmap.h | 72 - engines/wintermute/base/font/BFontStorage.cpp | 135 - engines/wintermute/base/font/BFontStorage.h | 55 - engines/wintermute/base/font/BFontTT.cpp | 762 ---- engines/wintermute/base/font/BFontTT.h | 180 - engines/wintermute/base/font/base_font.cpp | 206 + engines/wintermute/base/font/base_font.h | 61 + engines/wintermute/base/font/base_font_bitmap.cpp | 540 +++ engines/wintermute/base/font/base_font_bitmap.h | 72 + engines/wintermute/base/font/base_font_storage.cpp | 135 + engines/wintermute/base/font/base_font_storage.h | 55 + .../wintermute/base/font/base_font_truetype.cpp | 762 ++++ engines/wintermute/base/font/base_font_truetype.h | 180 + engines/wintermute/base/gfx/base_image.cpp | 8 +- engines/wintermute/base/gfx/base_image.h | 2 +- engines/wintermute/base/gfx/base_renderer.cpp | 6 +- engines/wintermute/base/gfx/base_renderer.h | 2 +- engines/wintermute/base/gfx/base_surface.cpp | 2 +- engines/wintermute/base/gfx/base_surface.h | 4 +- .../base/gfx/osystem/base_render_osystem.cpp | 12 +- .../base/gfx/osystem/base_surface_osystem.cpp | 8 +- engines/wintermute/base/particles/PartEmitter.cpp | 1199 ------ engines/wintermute/base/particles/PartEmitter.h | 139 - engines/wintermute/base/particles/PartForce.cpp | 59 - engines/wintermute/base/particles/PartForce.h | 57 - engines/wintermute/base/particles/PartParticle.cpp | 257 -- engines/wintermute/base/particles/PartParticle.h | 90 - engines/wintermute/base/particles/part_emitter.cpp | 1199 ++++++ engines/wintermute/base/particles/part_emitter.h | 139 + engines/wintermute/base/particles/part_force.cpp | 59 + engines/wintermute/base/particles/part_force.h | 57 + .../wintermute/base/particles/part_particle.cpp | 257 ++ engines/wintermute/base/particles/part_particle.h | 90 + engines/wintermute/base/scriptables/SXArray.cpp | 238 -- engines/wintermute/base/scriptables/SXArray.h | 54 - engines/wintermute/base/scriptables/SXDate.cpp | 297 -- engines/wintermute/base/scriptables/SXDate.h | 55 - engines/wintermute/base/scriptables/SXFile.cpp | 779 ---- engines/wintermute/base/scriptables/SXFile.h | 66 - engines/wintermute/base/scriptables/SXMath.cpp | 295 -- engines/wintermute/base/scriptables/SXMath.h | 53 - .../wintermute/base/scriptables/SXMemBuffer.cpp | 508 --- engines/wintermute/base/scriptables/SXMemBuffer.h | 59 - engines/wintermute/base/scriptables/SXString.cpp | 404 -- engines/wintermute/base/scriptables/SXString.h | 58 - engines/wintermute/base/scriptables/ScEngine.cpp | 712 ---- engines/wintermute/base/scriptables/ScEngine.h | 147 - engines/wintermute/base/scriptables/ScScript.cpp | 1461 ------- engines/wintermute/base/scriptables/ScScript.h | 183 - engines/wintermute/base/scriptables/ScStack.cpp | 226 - engines/wintermute/base/scriptables/ScStack.h | 66 - engines/wintermute/base/scriptables/ScValue.cpp | 1054 ----- engines/wintermute/base/scriptables/ScValue.h | 141 - engines/wintermute/base/scriptables/SxObject.cpp | 67 - engines/wintermute/base/scriptables/SxObject.h | 47 - engines/wintermute/base/scriptables/script.cpp | 1461 +++++++ engines/wintermute/base/scriptables/script.h | 183 + .../wintermute/base/scriptables/script_engine.cpp | 712 ++++ .../wintermute/base/scriptables/script_engine.h | 147 + .../base/scriptables/script_ext_array.cpp | 238 ++ .../wintermute/base/scriptables/script_ext_array.h | 54 + .../base/scriptables/script_ext_date.cpp | 297 ++ .../wintermute/base/scriptables/script_ext_date.h | 55 + .../base/scriptables/script_ext_file.cpp | 779 ++++ .../wintermute/base/scriptables/script_ext_file.h | 66 + .../base/scriptables/script_ext_math.cpp | 295 ++ .../wintermute/base/scriptables/script_ext_math.h | 53 + .../base/scriptables/script_ext_mem_buffer.cpp | 508 +++ .../base/scriptables/script_ext_mem_buffer.h | 59 + .../base/scriptables/script_ext_object.cpp | 67 + .../base/scriptables/script_ext_object.h | 47 + .../base/scriptables/script_ext_string.cpp | 404 ++ .../base/scriptables/script_ext_string.h | 58 + .../wintermute/base/scriptables/script_stack.cpp | 226 + engines/wintermute/base/scriptables/script_stack.h | 66 + .../wintermute/base/scriptables/script_value.cpp | 1054 +++++ engines/wintermute/base/scriptables/script_value.h | 141 + engines/wintermute/base/sound/base_sound.cpp | 288 ++ engines/wintermute/base/sound/base_sound.h | 88 + .../wintermute/base/sound/base_sound_buffer.cpp | 383 ++ engines/wintermute/base/sound/base_sound_buffer.h | 100 + .../wintermute/base/sound/base_sound_manager.cpp | 292 ++ engines/wintermute/base/sound/base_sound_manager.h | 69 + engines/wintermute/coll_templ.h | 4 +- engines/wintermute/detection.cpp | 2 +- engines/wintermute/graphics/transparentSurface.cpp | 427 -- engines/wintermute/graphics/transparentSurface.h | 124 - .../wintermute/graphics/transparent_surface.cpp | 427 ++ engines/wintermute/graphics/transparent_surface.h | 124 + engines/wintermute/math/MathUtil.cpp | 48 - engines/wintermute/math/MathUtil.h | 42 - engines/wintermute/math/Matrix4.cpp | 86 - engines/wintermute/math/Matrix4.h | 59 - engines/wintermute/math/Rect32.h | 86 - engines/wintermute/math/Vector2.cpp | 55 - engines/wintermute/math/Vector2.h | 75 - engines/wintermute/math/math_util.cpp | 48 + engines/wintermute/math/math_util.h | 42 + engines/wintermute/math/matrix4.cpp | 86 + engines/wintermute/math/matrix4.h | 59 + engines/wintermute/math/rect32.h | 86 + engines/wintermute/math/vector2.cpp | 55 + engines/wintermute/math/vector2.h | 75 + engines/wintermute/module.mk | 196 +- engines/wintermute/persistent.cpp | 122 +- engines/wintermute/persistent.h | 2 +- engines/wintermute/platform_osystem.cpp | 10 +- engines/wintermute/platform_osystem.h | 2 +- engines/wintermute/system/SysClass.cpp | 211 - engines/wintermute/system/SysClass.h | 130 - engines/wintermute/system/SysClassRegistry.cpp | 315 -- engines/wintermute/system/SysClassRegistry.h | 107 - engines/wintermute/system/SysInstance.cpp | 49 - engines/wintermute/system/SysInstance.h | 68 - engines/wintermute/system/sys_class.cpp | 211 + engines/wintermute/system/sys_class.h | 130 + engines/wintermute/system/sys_class_registry.cpp | 315 ++ engines/wintermute/system/sys_class_registry.h | 107 + engines/wintermute/system/sys_instance.cpp | 49 + engines/wintermute/system/sys_instance.h | 68 + engines/wintermute/ui/UIButton.cpp | 1046 ----- engines/wintermute/ui/UIButton.h | 79 - engines/wintermute/ui/UIEdit.cpp | 857 ---- engines/wintermute/ui/UIEdit.h | 72 - engines/wintermute/ui/UIEntity.cpp | 339 -- engines/wintermute/ui/UIEntity.h | 58 - engines/wintermute/ui/UIObject.cpp | 589 --- engines/wintermute/ui/UIObject.h | 83 - engines/wintermute/ui/UIText.cpp | 489 --- engines/wintermute/ui/UIText.h | 60 - engines/wintermute/ui/UITiledImage.cpp | 370 -- engines/wintermute/ui/UITiledImage.h | 63 - engines/wintermute/ui/UIWindow.cpp | 1327 ------ engines/wintermute/ui/UIWindow.h | 93 - engines/wintermute/ui/ui_button.cpp | 1046 +++++ engines/wintermute/ui/ui_button.h | 79 + engines/wintermute/ui/ui_edit.cpp | 857 ++++ engines/wintermute/ui/ui_edit.h | 72 + engines/wintermute/ui/ui_entity.cpp | 339 ++ engines/wintermute/ui/ui_entity.h | 58 + engines/wintermute/ui/ui_object.cpp | 589 +++ engines/wintermute/ui/ui_object.h | 83 + engines/wintermute/ui/ui_text.cpp | 489 +++ engines/wintermute/ui/ui_text.h | 60 + engines/wintermute/ui/ui_tiled_image.cpp | 370 ++ engines/wintermute/ui/ui_tiled_image.h | 63 + engines/wintermute/ui/ui_window.cpp | 1327 ++++++ engines/wintermute/ui/ui_window.h | 93 + engines/wintermute/utils/ConvertUTF.cpp | 612 --- engines/wintermute/utils/ConvertUTF.h | 149 - engines/wintermute/utils/PathUtil.cpp | 196 - engines/wintermute/utils/PathUtil.h | 56 - engines/wintermute/utils/StringUtil.cpp | 381 -- engines/wintermute/utils/StringUtil.h | 66 - engines/wintermute/utils/convert_utf.cpp | 612 +++ engines/wintermute/utils/convert_utf.h | 149 + engines/wintermute/utils/crc.cpp | 2 +- engines/wintermute/utils/path_util.cpp | 196 + engines/wintermute/utils/path_util.h | 56 + engines/wintermute/utils/string_util.cpp | 381 ++ engines/wintermute/utils/string_util.h | 66 + engines/wintermute/utils/utils.cpp | 6 +- engines/wintermute/utils/utils.h | 2 +- engines/wintermute/video/VidPlayer.cpp | 470 -- engines/wintermute/video/VidPlayer.h | 93 - engines/wintermute/video/VidTheoraPlayer.cpp | 850 ---- engines/wintermute/video/VidTheoraPlayer.h | 151 - engines/wintermute/video/video_player.cpp | 470 ++ engines/wintermute/video/video_player.h | 93 + engines/wintermute/video/video_theora_player.cpp | 850 ++++ engines/wintermute/video/video_theora_player.h | 151 + engines/wintermute/wintermute.cpp | 8 +- 417 files changed, 57622 insertions(+), 57618 deletions(-) delete mode 100644 engines/wintermute/ad/AdActor.cpp delete mode 100644 engines/wintermute/ad/AdActor.h delete mode 100644 engines/wintermute/ad/AdEntity.cpp delete mode 100644 engines/wintermute/ad/AdEntity.h delete mode 100644 engines/wintermute/ad/AdGame.cpp delete mode 100644 engines/wintermute/ad/AdGame.h delete mode 100644 engines/wintermute/ad/AdInventory.cpp delete mode 100644 engines/wintermute/ad/AdInventory.h delete mode 100644 engines/wintermute/ad/AdInventoryBox.cpp delete mode 100644 engines/wintermute/ad/AdInventoryBox.h delete mode 100644 engines/wintermute/ad/AdItem.cpp delete mode 100644 engines/wintermute/ad/AdItem.h delete mode 100644 engines/wintermute/ad/AdLayer.cpp delete mode 100644 engines/wintermute/ad/AdLayer.h delete mode 100644 engines/wintermute/ad/AdNodeState.cpp delete mode 100644 engines/wintermute/ad/AdNodeState.h delete mode 100644 engines/wintermute/ad/AdObject.cpp delete mode 100644 engines/wintermute/ad/AdObject.h delete mode 100644 engines/wintermute/ad/AdPath.cpp delete mode 100644 engines/wintermute/ad/AdPath.h delete mode 100644 engines/wintermute/ad/AdPathPoint.cpp delete mode 100644 engines/wintermute/ad/AdPathPoint.h delete mode 100644 engines/wintermute/ad/AdRegion.cpp delete mode 100644 engines/wintermute/ad/AdRegion.h delete mode 100644 engines/wintermute/ad/AdResponse.cpp delete mode 100644 engines/wintermute/ad/AdResponse.h delete mode 100644 engines/wintermute/ad/AdResponseBox.cpp delete mode 100644 engines/wintermute/ad/AdResponseBox.h delete mode 100644 engines/wintermute/ad/AdResponseContext.cpp delete mode 100644 engines/wintermute/ad/AdResponseContext.h delete mode 100644 engines/wintermute/ad/AdRotLevel.cpp delete mode 100644 engines/wintermute/ad/AdRotLevel.h delete mode 100644 engines/wintermute/ad/AdScaleLevel.cpp delete mode 100644 engines/wintermute/ad/AdScaleLevel.h delete mode 100644 engines/wintermute/ad/AdScene.cpp delete mode 100644 engines/wintermute/ad/AdScene.h delete mode 100644 engines/wintermute/ad/AdSceneNode.cpp delete mode 100644 engines/wintermute/ad/AdSceneNode.h delete mode 100644 engines/wintermute/ad/AdSceneState.cpp delete mode 100644 engines/wintermute/ad/AdSceneState.h delete mode 100644 engines/wintermute/ad/AdSentence.cpp delete mode 100644 engines/wintermute/ad/AdSentence.h delete mode 100644 engines/wintermute/ad/AdSpriteSet.cpp delete mode 100644 engines/wintermute/ad/AdSpriteSet.h delete mode 100644 engines/wintermute/ad/AdTalkDef.cpp delete mode 100644 engines/wintermute/ad/AdTalkDef.h delete mode 100644 engines/wintermute/ad/AdTalkHolder.cpp delete mode 100644 engines/wintermute/ad/AdTalkHolder.h delete mode 100644 engines/wintermute/ad/AdTalkNode.cpp delete mode 100644 engines/wintermute/ad/AdTalkNode.h delete mode 100644 engines/wintermute/ad/AdTypes.h delete mode 100644 engines/wintermute/ad/AdWaypointGroup.cpp delete mode 100644 engines/wintermute/ad/AdWaypointGroup.h create mode 100644 engines/wintermute/ad/ad_actor.cpp create mode 100644 engines/wintermute/ad/ad_actor.h create mode 100644 engines/wintermute/ad/ad_entity.cpp create mode 100644 engines/wintermute/ad/ad_entity.h create mode 100644 engines/wintermute/ad/ad_game.cpp create mode 100644 engines/wintermute/ad/ad_game.h create mode 100644 engines/wintermute/ad/ad_inventory.cpp create mode 100644 engines/wintermute/ad/ad_inventory.h create mode 100644 engines/wintermute/ad/ad_inventory_box.cpp create mode 100644 engines/wintermute/ad/ad_inventory_box.h create mode 100644 engines/wintermute/ad/ad_item.cpp create mode 100644 engines/wintermute/ad/ad_item.h create mode 100644 engines/wintermute/ad/ad_layer.cpp create mode 100644 engines/wintermute/ad/ad_layer.h create mode 100644 engines/wintermute/ad/ad_node_state.cpp create mode 100644 engines/wintermute/ad/ad_node_state.h create mode 100644 engines/wintermute/ad/ad_object.cpp create mode 100644 engines/wintermute/ad/ad_object.h create mode 100644 engines/wintermute/ad/ad_path.cpp create mode 100644 engines/wintermute/ad/ad_path.h create mode 100644 engines/wintermute/ad/ad_path_point.cpp create mode 100644 engines/wintermute/ad/ad_path_point.h create mode 100644 engines/wintermute/ad/ad_region.cpp create mode 100644 engines/wintermute/ad/ad_region.h create mode 100644 engines/wintermute/ad/ad_response.cpp create mode 100644 engines/wintermute/ad/ad_response.h create mode 100644 engines/wintermute/ad/ad_response_box.cpp create mode 100644 engines/wintermute/ad/ad_response_box.h create mode 100644 engines/wintermute/ad/ad_response_context.cpp create mode 100644 engines/wintermute/ad/ad_response_context.h create mode 100644 engines/wintermute/ad/ad_rot_level.cpp create mode 100644 engines/wintermute/ad/ad_rot_level.h create mode 100644 engines/wintermute/ad/ad_scale_level.cpp create mode 100644 engines/wintermute/ad/ad_scale_level.h create mode 100644 engines/wintermute/ad/ad_scene.cpp create mode 100644 engines/wintermute/ad/ad_scene.h create mode 100644 engines/wintermute/ad/ad_scene_node.cpp create mode 100644 engines/wintermute/ad/ad_scene_node.h create mode 100644 engines/wintermute/ad/ad_scene_state.cpp create mode 100644 engines/wintermute/ad/ad_scene_state.h create mode 100644 engines/wintermute/ad/ad_sentence.cpp create mode 100644 engines/wintermute/ad/ad_sentence.h create mode 100644 engines/wintermute/ad/ad_sprite_set.cpp create mode 100644 engines/wintermute/ad/ad_sprite_set.h create mode 100644 engines/wintermute/ad/ad_talk_def.cpp create mode 100644 engines/wintermute/ad/ad_talk_def.h create mode 100644 engines/wintermute/ad/ad_talk_holder.cpp create mode 100644 engines/wintermute/ad/ad_talk_holder.h create mode 100644 engines/wintermute/ad/ad_talk_node.cpp create mode 100644 engines/wintermute/ad/ad_talk_node.h create mode 100644 engines/wintermute/ad/ad_types.h create mode 100644 engines/wintermute/ad/ad_waypoint_group.cpp create mode 100644 engines/wintermute/ad/ad_waypoint_group.h delete mode 100644 engines/wintermute/base/BActiveRect.cpp delete mode 100644 engines/wintermute/base/BActiveRect.h delete mode 100644 engines/wintermute/base/BBase.cpp delete mode 100644 engines/wintermute/base/BBase.h delete mode 100644 engines/wintermute/base/BDebugger.cpp delete mode 100644 engines/wintermute/base/BDebugger.h delete mode 100644 engines/wintermute/base/BDynBuffer.cpp delete mode 100644 engines/wintermute/base/BDynBuffer.h delete mode 100644 engines/wintermute/base/BFader.cpp delete mode 100644 engines/wintermute/base/BFader.h delete mode 100644 engines/wintermute/base/BFileManager.cpp delete mode 100644 engines/wintermute/base/BFileManager.h delete mode 100644 engines/wintermute/base/BFrame.cpp delete mode 100644 engines/wintermute/base/BFrame.h delete mode 100644 engines/wintermute/base/BGame.cpp delete mode 100644 engines/wintermute/base/BGame.h delete mode 100644 engines/wintermute/base/BKeyboardState.cpp delete mode 100644 engines/wintermute/base/BKeyboardState.h delete mode 100644 engines/wintermute/base/BNamedObject.cpp delete mode 100644 engines/wintermute/base/BNamedObject.h delete mode 100644 engines/wintermute/base/BObject.cpp delete mode 100644 engines/wintermute/base/BObject.h delete mode 100644 engines/wintermute/base/BParser.cpp delete mode 100644 engines/wintermute/base/BParser.h delete mode 100644 engines/wintermute/base/BPersistMgr.cpp delete mode 100644 engines/wintermute/base/BPersistMgr.h delete mode 100644 engines/wintermute/base/BPoint.cpp delete mode 100644 engines/wintermute/base/BPoint.h delete mode 100644 engines/wintermute/base/BQuickMsg.cpp delete mode 100644 engines/wintermute/base/BQuickMsg.h delete mode 100644 engines/wintermute/base/BRegion.cpp delete mode 100644 engines/wintermute/base/BRegion.h delete mode 100644 engines/wintermute/base/BRegistry.cpp delete mode 100644 engines/wintermute/base/BRegistry.h delete mode 100644 engines/wintermute/base/BResources.cpp delete mode 100644 engines/wintermute/base/BResources.h delete mode 100644 engines/wintermute/base/BSaveThumbHelper.cpp delete mode 100644 engines/wintermute/base/BSaveThumbHelper.h delete mode 100644 engines/wintermute/base/BScriptHolder.cpp delete mode 100644 engines/wintermute/base/BScriptHolder.h delete mode 100644 engines/wintermute/base/BScriptable.cpp delete mode 100644 engines/wintermute/base/BScriptable.h delete mode 100644 engines/wintermute/base/BSound.cpp delete mode 100644 engines/wintermute/base/BSound.h delete mode 100644 engines/wintermute/base/BSoundBuffer.cpp delete mode 100644 engines/wintermute/base/BSoundBuffer.h delete mode 100644 engines/wintermute/base/BSoundMgr.cpp delete mode 100644 engines/wintermute/base/BSoundMgr.h delete mode 100644 engines/wintermute/base/BSprite.cpp delete mode 100644 engines/wintermute/base/BSprite.h delete mode 100644 engines/wintermute/base/BStringTable.cpp delete mode 100644 engines/wintermute/base/BStringTable.h delete mode 100644 engines/wintermute/base/BSubFrame.cpp delete mode 100644 engines/wintermute/base/BSubFrame.h delete mode 100644 engines/wintermute/base/BSurfaceStorage.cpp delete mode 100644 engines/wintermute/base/BSurfaceStorage.h delete mode 100644 engines/wintermute/base/BTransitionMgr.cpp delete mode 100644 engines/wintermute/base/BTransitionMgr.h delete mode 100644 engines/wintermute/base/BViewport.cpp delete mode 100644 engines/wintermute/base/BViewport.h create mode 100644 engines/wintermute/base/base.cpp create mode 100644 engines/wintermute/base/base.h create mode 100644 engines/wintermute/base/base_active_rect.cpp create mode 100644 engines/wintermute/base/base_active_rect.h create mode 100644 engines/wintermute/base/base_debugger.cpp create mode 100644 engines/wintermute/base/base_debugger.h create mode 100644 engines/wintermute/base/base_dynamic_buffer.cpp create mode 100644 engines/wintermute/base/base_dynamic_buffer.h create mode 100644 engines/wintermute/base/base_fader.cpp create mode 100644 engines/wintermute/base/base_fader.h create mode 100644 engines/wintermute/base/base_file_manager.cpp create mode 100644 engines/wintermute/base/base_file_manager.h create mode 100644 engines/wintermute/base/base_frame.cpp create mode 100644 engines/wintermute/base/base_frame.h create mode 100644 engines/wintermute/base/base_game.cpp create mode 100644 engines/wintermute/base/base_game.h create mode 100644 engines/wintermute/base/base_keyboard_state.cpp create mode 100644 engines/wintermute/base/base_keyboard_state.h create mode 100644 engines/wintermute/base/base_named_object.cpp create mode 100644 engines/wintermute/base/base_named_object.h create mode 100644 engines/wintermute/base/base_object.cpp create mode 100644 engines/wintermute/base/base_object.h create mode 100644 engines/wintermute/base/base_parser.cpp create mode 100644 engines/wintermute/base/base_parser.h create mode 100644 engines/wintermute/base/base_persistence_manager.cpp create mode 100644 engines/wintermute/base/base_persistence_manager.h create mode 100644 engines/wintermute/base/base_point.cpp create mode 100644 engines/wintermute/base/base_point.h create mode 100644 engines/wintermute/base/base_quick_msg.cpp create mode 100644 engines/wintermute/base/base_quick_msg.h create mode 100644 engines/wintermute/base/base_region.cpp create mode 100644 engines/wintermute/base/base_region.h create mode 100644 engines/wintermute/base/base_registry.cpp create mode 100644 engines/wintermute/base/base_registry.h create mode 100644 engines/wintermute/base/base_save_thumb_helper.cpp create mode 100644 engines/wintermute/base/base_save_thumb_helper.h create mode 100644 engines/wintermute/base/base_script_holder.cpp create mode 100644 engines/wintermute/base/base_script_holder.h create mode 100644 engines/wintermute/base/base_scriptable.cpp create mode 100644 engines/wintermute/base/base_scriptable.h create mode 100644 engines/wintermute/base/base_sprite.cpp create mode 100644 engines/wintermute/base/base_sprite.h create mode 100644 engines/wintermute/base/base_string_table.cpp create mode 100644 engines/wintermute/base/base_string_table.h create mode 100644 engines/wintermute/base/base_sub_frame.cpp create mode 100644 engines/wintermute/base/base_sub_frame.h create mode 100644 engines/wintermute/base/base_surface_storage.cpp create mode 100644 engines/wintermute/base/base_surface_storage.h create mode 100644 engines/wintermute/base/base_transition_manager.cpp create mode 100644 engines/wintermute/base/base_transition_manager.h create mode 100644 engines/wintermute/base/base_viewport.cpp create mode 100644 engines/wintermute/base/base_viewport.h delete mode 100644 engines/wintermute/base/file/BDiskFile.cpp delete mode 100644 engines/wintermute/base/file/BDiskFile.h delete mode 100644 engines/wintermute/base/file/BFile.cpp delete mode 100644 engines/wintermute/base/file/BFile.h delete mode 100644 engines/wintermute/base/file/BFileEntry.cpp delete mode 100644 engines/wintermute/base/file/BFileEntry.h delete mode 100644 engines/wintermute/base/file/BPackage.cpp delete mode 100644 engines/wintermute/base/file/BPackage.h delete mode 100644 engines/wintermute/base/file/BSaveThumbFile.cpp delete mode 100644 engines/wintermute/base/file/BSaveThumbFile.h create mode 100644 engines/wintermute/base/file/base_disk_file.cpp create mode 100644 engines/wintermute/base/file/base_disk_file.h create mode 100644 engines/wintermute/base/file/base_file.cpp create mode 100644 engines/wintermute/base/file/base_file.h create mode 100644 engines/wintermute/base/file/base_file_entry.cpp create mode 100644 engines/wintermute/base/file/base_file_entry.h create mode 100644 engines/wintermute/base/file/base_package.cpp create mode 100644 engines/wintermute/base/file/base_package.h create mode 100644 engines/wintermute/base/file/base_resources.cpp create mode 100644 engines/wintermute/base/file/base_resources.h create mode 100644 engines/wintermute/base/file/base_save_thumb_file.cpp create mode 100644 engines/wintermute/base/file/base_save_thumb_file.h delete mode 100644 engines/wintermute/base/font/BFont.cpp delete mode 100644 engines/wintermute/base/font/BFont.h delete mode 100644 engines/wintermute/base/font/BFontBitmap.cpp delete mode 100644 engines/wintermute/base/font/BFontBitmap.h delete mode 100644 engines/wintermute/base/font/BFontStorage.cpp delete mode 100644 engines/wintermute/base/font/BFontStorage.h delete mode 100644 engines/wintermute/base/font/BFontTT.cpp delete mode 100644 engines/wintermute/base/font/BFontTT.h create mode 100644 engines/wintermute/base/font/base_font.cpp create mode 100644 engines/wintermute/base/font/base_font.h create mode 100644 engines/wintermute/base/font/base_font_bitmap.cpp create mode 100644 engines/wintermute/base/font/base_font_bitmap.h create mode 100644 engines/wintermute/base/font/base_font_storage.cpp create mode 100644 engines/wintermute/base/font/base_font_storage.h create mode 100644 engines/wintermute/base/font/base_font_truetype.cpp create mode 100644 engines/wintermute/base/font/base_font_truetype.h delete mode 100644 engines/wintermute/base/particles/PartEmitter.cpp delete mode 100644 engines/wintermute/base/particles/PartEmitter.h delete mode 100644 engines/wintermute/base/particles/PartForce.cpp delete mode 100644 engines/wintermute/base/particles/PartForce.h delete mode 100644 engines/wintermute/base/particles/PartParticle.cpp delete mode 100644 engines/wintermute/base/particles/PartParticle.h create mode 100644 engines/wintermute/base/particles/part_emitter.cpp create mode 100644 engines/wintermute/base/particles/part_emitter.h create mode 100644 engines/wintermute/base/particles/part_force.cpp create mode 100644 engines/wintermute/base/particles/part_force.h create mode 100644 engines/wintermute/base/particles/part_particle.cpp create mode 100644 engines/wintermute/base/particles/part_particle.h delete mode 100644 engines/wintermute/base/scriptables/SXArray.cpp delete mode 100644 engines/wintermute/base/scriptables/SXArray.h delete mode 100644 engines/wintermute/base/scriptables/SXDate.cpp delete mode 100644 engines/wintermute/base/scriptables/SXDate.h delete mode 100644 engines/wintermute/base/scriptables/SXFile.cpp delete mode 100644 engines/wintermute/base/scriptables/SXFile.h delete mode 100644 engines/wintermute/base/scriptables/SXMath.cpp delete mode 100644 engines/wintermute/base/scriptables/SXMath.h delete mode 100644 engines/wintermute/base/scriptables/SXMemBuffer.cpp delete mode 100644 engines/wintermute/base/scriptables/SXMemBuffer.h delete mode 100644 engines/wintermute/base/scriptables/SXString.cpp delete mode 100644 engines/wintermute/base/scriptables/SXString.h delete mode 100644 engines/wintermute/base/scriptables/ScEngine.cpp delete mode 100644 engines/wintermute/base/scriptables/ScEngine.h delete mode 100644 engines/wintermute/base/scriptables/ScScript.cpp delete mode 100644 engines/wintermute/base/scriptables/ScScript.h delete mode 100644 engines/wintermute/base/scriptables/ScStack.cpp delete mode 100644 engines/wintermute/base/scriptables/ScStack.h delete mode 100644 engines/wintermute/base/scriptables/ScValue.cpp delete mode 100644 engines/wintermute/base/scriptables/ScValue.h delete mode 100644 engines/wintermute/base/scriptables/SxObject.cpp delete mode 100644 engines/wintermute/base/scriptables/SxObject.h create mode 100644 engines/wintermute/base/scriptables/script.cpp create mode 100644 engines/wintermute/base/scriptables/script.h create mode 100644 engines/wintermute/base/scriptables/script_engine.cpp create mode 100644 engines/wintermute/base/scriptables/script_engine.h create mode 100644 engines/wintermute/base/scriptables/script_ext_array.cpp create mode 100644 engines/wintermute/base/scriptables/script_ext_array.h create mode 100644 engines/wintermute/base/scriptables/script_ext_date.cpp create mode 100644 engines/wintermute/base/scriptables/script_ext_date.h create mode 100644 engines/wintermute/base/scriptables/script_ext_file.cpp create mode 100644 engines/wintermute/base/scriptables/script_ext_file.h create mode 100644 engines/wintermute/base/scriptables/script_ext_math.cpp create mode 100644 engines/wintermute/base/scriptables/script_ext_math.h create mode 100644 engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp create mode 100644 engines/wintermute/base/scriptables/script_ext_mem_buffer.h create mode 100644 engines/wintermute/base/scriptables/script_ext_object.cpp create mode 100644 engines/wintermute/base/scriptables/script_ext_object.h create mode 100644 engines/wintermute/base/scriptables/script_ext_string.cpp create mode 100644 engines/wintermute/base/scriptables/script_ext_string.h create mode 100644 engines/wintermute/base/scriptables/script_stack.cpp create mode 100644 engines/wintermute/base/scriptables/script_stack.h create mode 100644 engines/wintermute/base/scriptables/script_value.cpp create mode 100644 engines/wintermute/base/scriptables/script_value.h create mode 100644 engines/wintermute/base/sound/base_sound.cpp create mode 100644 engines/wintermute/base/sound/base_sound.h create mode 100644 engines/wintermute/base/sound/base_sound_buffer.cpp create mode 100644 engines/wintermute/base/sound/base_sound_buffer.h create mode 100644 engines/wintermute/base/sound/base_sound_manager.cpp create mode 100644 engines/wintermute/base/sound/base_sound_manager.h delete mode 100644 engines/wintermute/graphics/transparentSurface.cpp delete mode 100644 engines/wintermute/graphics/transparentSurface.h create mode 100644 engines/wintermute/graphics/transparent_surface.cpp create mode 100644 engines/wintermute/graphics/transparent_surface.h delete mode 100644 engines/wintermute/math/MathUtil.cpp delete mode 100644 engines/wintermute/math/MathUtil.h delete mode 100644 engines/wintermute/math/Matrix4.cpp delete mode 100644 engines/wintermute/math/Matrix4.h delete mode 100644 engines/wintermute/math/Rect32.h delete mode 100644 engines/wintermute/math/Vector2.cpp delete mode 100644 engines/wintermute/math/Vector2.h create mode 100644 engines/wintermute/math/math_util.cpp create mode 100644 engines/wintermute/math/math_util.h create mode 100644 engines/wintermute/math/matrix4.cpp create mode 100644 engines/wintermute/math/matrix4.h create mode 100644 engines/wintermute/math/rect32.h create mode 100644 engines/wintermute/math/vector2.cpp create mode 100644 engines/wintermute/math/vector2.h delete mode 100644 engines/wintermute/system/SysClass.cpp delete mode 100644 engines/wintermute/system/SysClass.h delete mode 100644 engines/wintermute/system/SysClassRegistry.cpp delete mode 100644 engines/wintermute/system/SysClassRegistry.h delete mode 100644 engines/wintermute/system/SysInstance.cpp delete mode 100644 engines/wintermute/system/SysInstance.h create mode 100644 engines/wintermute/system/sys_class.cpp create mode 100644 engines/wintermute/system/sys_class.h create mode 100644 engines/wintermute/system/sys_class_registry.cpp create mode 100644 engines/wintermute/system/sys_class_registry.h create mode 100644 engines/wintermute/system/sys_instance.cpp create mode 100644 engines/wintermute/system/sys_instance.h delete mode 100644 engines/wintermute/ui/UIButton.cpp delete mode 100644 engines/wintermute/ui/UIButton.h delete mode 100644 engines/wintermute/ui/UIEdit.cpp delete mode 100644 engines/wintermute/ui/UIEdit.h delete mode 100644 engines/wintermute/ui/UIEntity.cpp delete mode 100644 engines/wintermute/ui/UIEntity.h delete mode 100644 engines/wintermute/ui/UIObject.cpp delete mode 100644 engines/wintermute/ui/UIObject.h delete mode 100644 engines/wintermute/ui/UIText.cpp delete mode 100644 engines/wintermute/ui/UIText.h delete mode 100644 engines/wintermute/ui/UITiledImage.cpp delete mode 100644 engines/wintermute/ui/UITiledImage.h delete mode 100644 engines/wintermute/ui/UIWindow.cpp delete mode 100644 engines/wintermute/ui/UIWindow.h create mode 100644 engines/wintermute/ui/ui_button.cpp create mode 100644 engines/wintermute/ui/ui_button.h create mode 100644 engines/wintermute/ui/ui_edit.cpp create mode 100644 engines/wintermute/ui/ui_edit.h create mode 100644 engines/wintermute/ui/ui_entity.cpp create mode 100644 engines/wintermute/ui/ui_entity.h create mode 100644 engines/wintermute/ui/ui_object.cpp create mode 100644 engines/wintermute/ui/ui_object.h create mode 100644 engines/wintermute/ui/ui_text.cpp create mode 100644 engines/wintermute/ui/ui_text.h create mode 100644 engines/wintermute/ui/ui_tiled_image.cpp create mode 100644 engines/wintermute/ui/ui_tiled_image.h create mode 100644 engines/wintermute/ui/ui_window.cpp create mode 100644 engines/wintermute/ui/ui_window.h delete mode 100644 engines/wintermute/utils/ConvertUTF.cpp delete mode 100644 engines/wintermute/utils/ConvertUTF.h delete mode 100644 engines/wintermute/utils/PathUtil.cpp delete mode 100644 engines/wintermute/utils/PathUtil.h delete mode 100644 engines/wintermute/utils/StringUtil.cpp delete mode 100644 engines/wintermute/utils/StringUtil.h create mode 100644 engines/wintermute/utils/convert_utf.cpp create mode 100644 engines/wintermute/utils/convert_utf.h create mode 100644 engines/wintermute/utils/path_util.cpp create mode 100644 engines/wintermute/utils/path_util.h create mode 100644 engines/wintermute/utils/string_util.cpp create mode 100644 engines/wintermute/utils/string_util.h delete mode 100644 engines/wintermute/video/VidPlayer.cpp delete mode 100644 engines/wintermute/video/VidPlayer.h delete mode 100644 engines/wintermute/video/VidTheoraPlayer.cpp delete mode 100644 engines/wintermute/video/VidTheoraPlayer.h create mode 100644 engines/wintermute/video/video_player.cpp create mode 100644 engines/wintermute/video/video_player.h create mode 100644 engines/wintermute/video/video_theora_player.cpp create mode 100644 engines/wintermute/video/video_theora_player.h (limited to 'engines') diff --git a/engines/wintermute/ad/AdActor.cpp b/engines/wintermute/ad/AdActor.cpp deleted file mode 100644 index 050a419e53..0000000000 --- a/engines/wintermute/ad/AdActor.cpp +++ /dev/null @@ -1,1316 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/dctypes.h" -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/base/BObject.h" -#include "engines/wintermute/ad/AdActor.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/ad/AdScene.h" -#include "engines/wintermute/ad/AdEntity.h" -#include "engines/wintermute/ad/AdSpriteSet.h" -#include "engines/wintermute/ad/AdWaypointGroup.h" -#include "engines/wintermute/ad/AdPath.h" -#include "engines/wintermute/ad/AdSentence.h" -#include "engines/wintermute/base/BObject.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/wintermute.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdActor, false) - - -////////////////////////////////////////////////////////////////////////// -CAdActor::CAdActor(CBGame *inGame): CAdTalkHolder(inGame) { - _path = new CAdPath(_gameRef); - - _type = OBJECT_ACTOR; - _dir = DI_LEFT; - - _walkSprite = NULL; - _standSprite = NULL; - _turnLeftSprite = NULL; - _turnRightSprite = NULL; - - _targetPoint = new CBPoint; - _afterWalkDir = DI_NONE; - - _animSprite2 = NULL; - - setDefaultAnimNames(); -} - -////////////////////////////////////////////////////////////////////////// -bool CAdActor::setDefaultAnimNames() { - _talkAnimName = "talk"; - _idleAnimName = "idle"; - _walkAnimName = "walk"; - _turnLeftAnimName = "turnleft"; - _turnRightAnimName = "turnright"; - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -CAdActor::~CAdActor() { - 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 (int i = 0; i < _talkSprites.getSize(); i++) { - delete _talkSprites[i]; - } - _talkSprites.removeAll(); - - for (int i = 0; i < _talkSpritesEx.getSize(); i++) { - delete _talkSpritesEx[i]; - } - _talkSpritesEx.removeAll(); - - for (int i = 0; i < _anims.getSize(); i++) { - delete _anims[i]; - _anims[i] = NULL; - } - _anims.removeAll(); - -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdActor::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdActor::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdActor::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; - CBParser parser(_gameRef); - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ACTOR) { - _gameRef->LOG(0, "'ACTOR' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - CAdGame *adGame = (CAdGame *)_gameRef; - CAdSpriteSet *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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CBSprite(_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; - CBRegion *rgn = new CBRegion(_gameRef); - CBRegion *crgn = new CBRegion(_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; - CAdWaypointGroup *wpt = new CAdWaypointGroup(_gameRef); - CAdWaypointGroup *cwpt = new CAdWaypointGroup(_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: { - CAdSpriteSet *Anim = new CAdSpriteSet(_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 CAdActor::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 CAdActor::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; - - ((CAdGame *)_gameRef)->_scene->correctTargetPoint(_posX, _posY, &_targetPoint->x, &_targetPoint->y, true, this); - - _state = STATE_SEARCHING_PATH; - -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdActor::display() { - if (_active) updateSounds(); - - uint32 alpha; - if (_alphaColor != 0) alpha = _alphaColor; - else alpha = _shadowable ? ((CAdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY, true) : 0xFFFFFFFF; - - float scaleX, scaleY; - getScale(&scaleX, &scaleY); - - - float rotate; - if (_rotatable) { - if (_rotateValid) rotate = _rotate; - else rotate = ((CAdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; - } else rotate = 0.0f; - - if (_active) displaySpriteAttachments(true); - - if (_currentSprite && _active) { - bool reg = _registrable; - if (_ignoreItems && ((CAdGame *)_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 CAdActor::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 { - CAdSpriteSet *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 { - CAdSpriteSet *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 { - CAdSpriteSet *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 (((CAdGame *)_gameRef)->_scene->getPath(CBPoint(_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; - ((CAdGame *)_gameRef)->addSentence(_sentence); - } - } - } else { - _currentSprite = _tempSprite2; - ((CAdGame *)_gameRef)->addSentence(_sentence); - } - } - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_READY: - if (!_animSprite && !_animSprite2) { - if (_sprite) _currentSprite = _sprite; - else { - if (_standSprite) { - _currentSprite = _standSprite->getSprite(_dir); - } else { - CAdSpriteSet *Anim = getAnimByName(_idleAnimName); - if (Anim) _currentSprite = Anim->getSprite(_dir); - } - } - } - break; - default: - error("AdActor::Update - Unhandled enum"); - } - - - if (_currentSprite && !already_moved) { - _currentSprite->GetCurrentFrame(_zoomable ? ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((CAdGame *)_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 CAdActor::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(CBPoint(_posX, _posY), *_path->getCurrent()); - } else { - if (_afterWalkDir != DI_NONE) turnTo(_afterWalkDir); - else _state = STATE_READY; - } -} - - -////////////////////////////////////////////////////////////////////////// -void CAdActor::getNextStep() { - if (_walkSprite) { - _currentSprite = _walkSprite->getSprite(_dir); - } else { - CAdSpriteSet *Anim = getAnimByName(_walkAnimName); - if (Anim) _currentSprite = Anim->getSprite(_dir); - } - - if (!_currentSprite) return; - - _currentSprite->GetCurrentFrame(_zoomable ? ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((CAdGame *)_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 (((CAdGame *)_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(CBPoint(_posX, _posY), *_path->getCurrent()); - } -} - - -////////////////////////////////////////////////////////////////////////// -void CAdActor::initLine(CBPoint startPt, CBPoint 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 CAdActor::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); - CScValue *Val = stack->pop(); - if (!Val->isNative()) { - script->runtimeError("actor.%s method accepts an entity refrence only", name); - stack->pushNULL(); - return STATUS_OK; - } - CAdObject *Obj = (CAdObject *)Val->getNative(); - if (!Obj || Obj->_type != OBJECT_ENTITY) { - script->runtimeError("actor.%s method accepts an entity refrence only", name); - stack->pushNULL(); - return STATUS_OK; - } - CAdEntity *Ent = (CAdEntity *)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; - CScValue *val = stack->pop(); - - // turn to object? - if (val->isNative() && _gameRef->validObject((CBObject *)val->getNative())) { - CBObject *obj = (CBObject *)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 (int i = 0; i < _anims.getSize(); i++) { - if (scumm_stricmp(_anims[i]->_name, 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.removeAt(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 CAdTalkHolder::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdActor::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 CAdTalkHolder::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdActor::scSetProperty(const char *name, CScValue *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 CAdTalkHolder::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdActor::scToString() { - return "[actor object]"; -} - - -////////////////////////////////////////////////////////////////////////// -CBSprite *CAdActor::getTalkStance(const char *stance) { - // forced stance? - if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { - _forcedTalkAnimUsed = true; - delete _animSprite; - _animSprite = new CBSprite(_gameRef, this); - if (_animSprite) { - bool res = _animSprite->loadFile(_forcedTalkAnimName); - if (DID_FAIL(res)) { - _gameRef->LOG(res, "CAdActor::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", _name, _forcedTalkAnimName); - delete _animSprite; - _animSprite = NULL; - } else return _animSprite; - } - } - - // old way - if (_talkSprites.getSize() > 0 || _talkSpritesEx.getSize() > 0) - return getTalkStanceOld(stance); - - // new way - CBSprite *ret = NULL; - - // do we have an animation with this name? - CAdSpriteSet *Anim = getAnimByName(stance); - if (Anim) ret = Anim->getSprite(_dir); - - // not - get a random talk - if (!ret) { - CBArray TalkAnims; - for (int i = 0; i < _anims.getSize(); i++) { - if (_talkAnimName.compareToIgnoreCase(_anims[i]->_name) == 0) - TalkAnims.add(_anims[i]); - } - - if (TalkAnims.getSize() > 0) { - int rnd = g_wintermute->randInt(0, TalkAnims.getSize() - 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; -} - -////////////////////////////////////////////////////////////////////////// -CBSprite *CAdActor::getTalkStanceOld(const char *stance) { - CBSprite *ret = NULL; - - if (stance != NULL) { - // search special stances - for (int i = 0; i < _talkSpritesEx.getSize(); i++) { - if (scumm_stricmp(_talkSpritesEx[i]->_name, stance) == 0) { - ret = _talkSpritesEx[i]->getSprite(_dir); - break; - } - } - if (ret == NULL) { - // search generic stances - for (int i = 0; i < _talkSprites.getSize(); i++) { - if (scumm_stricmp(_talkSprites[i]->_name, stance) == 0) { - ret = _talkSprites[i]->getSprite(_dir); - break; - } - } - } - } - - // not a valid stance? get a random one - if (ret == NULL) { - if (_talkSprites.getSize() < 1) ret = _standSprite->getSprite(_dir); - else { - // TODO: remember last - int rnd = g_wintermute->randInt(0, _talkSprites.getSize() - 1); - ret = _talkSprites[rnd]->getSprite(_dir); - } - } - - return ret; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdActor::persist(CBPersistMgr *persistMgr) { - CAdTalkHolder::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 CAdActor::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 CAdActor::getHeight() { - // if no current sprite is set, set some - if (_currentSprite == NULL) { - if (_standSprite) _currentSprite = _standSprite->getSprite(_dir); - else { - CAdSpriteSet *Anim = getAnimByName(_idleAnimName); - if (Anim) _currentSprite = Anim->getSprite(_dir); - } - } - // and get height - return CAdTalkHolder::getHeight(); -} - - -////////////////////////////////////////////////////////////////////////// -CAdSpriteSet *CAdActor::getAnimByName(const Common::String &animName) { - for (int i = 0; i < _anims.getSize(); i++) { - if (animName.compareToIgnoreCase(_anims[i]->_name) == 0) - return _anims[i]; - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdActor::mergeAnims(const char *animsFilename) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ANIMATION) - TOKEN_TABLE_END - - - byte *fileBuffer = _gameRef->_fileManager->readWholeFile(animsFilename); - if (fileBuffer == NULL) { - _gameRef->LOG(0, "CAdActor::MergeAnims failed for file '%s'", animsFilename); - return STATUS_FAILED; - } - - byte *buffer = fileBuffer; - byte *params; - int cmd; - CBParser parser(_gameRef); - - bool Ret = STATUS_OK; - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_ANIMATION: { - CAdSpriteSet *Anim = new CAdSpriteSet(_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 CAdActor::playAnim(const char *filename) { - // if we have an anim with this name, use it - CAdSpriteSet *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 CAdTalkHolder::playAnim(filename); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdActor.h b/engines/wintermute/ad/AdActor.h deleted file mode 100644 index 1be8b8131d..0000000000 --- a/engines/wintermute/ad/AdActor.h +++ /dev/null @@ -1,107 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/AdTypes.h" // Added by ClassView -#include "engines/wintermute/ad/AdTalkHolder.h" -#include "engines/wintermute/base/BPoint.h" // Added by ClassView -#include "engines/wintermute/persistent.h" -#include "common/str.h" - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -namespace WinterMute { -class CAdSpriteSet; -class CAdPath; -class CAdActor : public CAdTalkHolder { -public: - TDirection angleToDirection(int angle); - DECLARE_PERSISTENT(CAdActor, CAdTalkHolder) - virtual int getHeight(); - CBSprite *getTalkStance(const char *stance); - virtual void goTo(int x, int y, TDirection afterWalkDir = DI_NONE); - CBPoint *_targetPoint; - virtual bool update(); - virtual bool display(); - TDirection _targetDir; - TDirection _afterWalkDir; - virtual void turnTo(TDirection dir); - CAdPath *_path; - CAdSpriteSet *_walkSprite; - CAdSpriteSet *_standSprite; - CAdSpriteSet *_turnLeftSprite; - CAdSpriteSet *_turnRightSprite; - CBArray _talkSprites; - CBArray _talkSpritesEx; - TDirection _dir; - CAdActor(CBGame *inGame/*=NULL*/); - virtual ~CAdActor(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - - // new anim system - Common::String _talkAnimName; - Common::String _idleAnimName; - Common::String _walkAnimName; - Common::String _turnLeftAnimName; - Common::String _turnRightAnimName; - CBArray _anims; - virtual bool playAnim(const char *filename); - CAdSpriteSet *getAnimByName(const Common::String &animName); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - -private: - bool setDefaultAnimNames(); - CBSprite *getTalkStanceOld(const char *stance); - bool mergeAnims(const char *animsFilename); - CBSprite *_animSprite2; - - void initLine(CBPoint startPt, CBPoint endPt); - void getNextStep(); - void followPath(); - double _pFStepX; - double _pFStepY; - double _pFX; - double _pFY; - int _pFCount; -}; - -} // end of namespace WinterMute - -#endif // WINTERMUTE_ADACTOR_H diff --git a/engines/wintermute/ad/AdEntity.cpp b/engines/wintermute/ad/AdEntity.cpp deleted file mode 100644 index 49c723f66a..0000000000 --- a/engines/wintermute/ad/AdEntity.cpp +++ /dev/null @@ -1,1027 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdEntity.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BActiveRect.h" -#include "engines/wintermute/base/BSurfaceStorage.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/ad/AdScene.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/ad/AdWaypointGroup.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/ad/AdSentence.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/video/VidTheoraPlayer.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdEntity, false) - -////////////////////////////////////////////////////////////////////////// -CAdEntity::CAdEntity(CBGame *inGame): CAdTalkHolder(inGame) { - _type = OBJECT_ENTITY; - _subtype = ENTITY_NORMAL; - _region = NULL; - _item = NULL; - - _walkToX = _walkToY = 0; - _walkToDir = DI_NONE; - - _theora = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdEntity::~CAdEntity() { - _gameRef->unregisterObject(_region); - - delete _theora; - _theora = NULL; - - delete[] _item; - _item = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdEntity::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdEntity::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdEntity::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; - CBParser parser(_gameRef); - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ENTITY) { - _gameRef->LOG(0, "'ENTITY' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - CAdGame *adGame = (CAdGame *)_gameRef; - CBSprite *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 CBSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params))) cmd = PARSERR_GENERIC; - else _sprite = spr; - } - break; - - case TOKEN_TALK: { - spr = new CBSprite(_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 CBSprite(_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 CBSprite(_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; - CBRegion *rgn = new CBRegion(_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; - CBRegion *rgn = new CBRegion(_gameRef); - CBRegion *crgn = new CBRegion(_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; - CAdWaypointGroup *wpt = new CAdWaypointGroup(_gameRef); - CAdWaypointGroup *cwpt = new CAdWaypointGroup(_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 CBSprite(_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.", _name); - } - - 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 && ((CAdGame *)_gameRef)->isItemTaken(_item)) _active = false; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdEntity::display() { - if (_active) { - updateSounds(); - - uint32 Alpha; - if (_alphaColor != 0) Alpha = _alphaColor; - else Alpha = _shadowable ? ((CAdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY) : 0xFFFFFFFF; - - float ScaleX, ScaleY; - getScale(&ScaleX, &ScaleY); - - float Rotate; - if (_rotatable) { - if (_rotateValid) Rotate = _rotate; - else Rotate = ((CAdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; - } else Rotate = 0.0f; - - - bool Reg = _registrable; - if (_ignoreItems && ((CAdGame *)_gameRef)->_selectedItem) Reg = false; - - if (_region && (Reg || _editorAlwaysRegister)) { - _gameRef->_renderer->_rectList.add(new CBActiveRect(_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 CAdEntity::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; - } - ((CAdGame *)_gameRef)->addSentence(_sentence); - } - } else { - _currentSprite = _tempSprite2; - ((CAdGame *)_gameRef)->addSentence(_sentence); - } - } - break; - default: // Silence unhandled enum-warning - break; - } - - - if (_currentSprite) { - _currentSprite->GetCurrentFrame(_zoomable ? ((CAdGame *)_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 CAdEntity::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); - CScValue *valAlpha = stack->pop(); - int startTime = stack->pop()->getInt(); - - delete _theora; - _theora = new CVidTheoraPlayer(_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(m_Scale>=0) m_Theora->m_PlayZoom = m_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 CBRegion(_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 CAdTalkHolder::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdEntity::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 CAdTalkHolder::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdEntity::scSetProperty(const char *name, CScValue *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 CAdTalkHolder::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdEntity::scToString() { - return "[entity object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdEntity::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "ENTITY {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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); - - int i; - - for (i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - if (_subtype == ENTITY_NORMAL && _sprite && _sprite->_filename) - buffer->putTextIndent(indent + 2, "SPRITE=\"%s\"\n", _sprite->_filename); - - if (_subtype == ENTITY_SOUND && _sFX && _sFX->_soundFilename) { - buffer->putTextIndent(indent + 2, "SOUND=\"%s\"\n", _sFX->_soundFilename); - 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->_filename) - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); - - if (_cursor && _cursor->_filename) - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); - - CAdTalkHolder::saveAsText(buffer, indent + 2); - - if (_region) _region->saveAsText(buffer, indent + 2); - - if (_scProp) _scProp->saveAsText(buffer, indent + 2); - - CAdObject::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CAdEntity::getHeight() { - if (_region && !_sprite) { - return _region->_rect.bottom - _region->_rect.top; - } else { - if (_currentSprite == NULL) _currentSprite = _sprite; - return CAdObject::getHeight(); - } -} - - -////////////////////////////////////////////////////////////////////////// -void CAdEntity::updatePosition() { - if (_region && !_sprite) { - _posX = _region->_rect.left + (_region->_rect.right - _region->_rect.left) / 2; - _posY = _region->_rect.bottom; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdEntity::persist(CBPersistMgr *persistMgr) { - CAdTalkHolder::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 CAdEntity::setItem(const char *itemName) { - CBUtils::setString(&_item, itemName); -} - -////////////////////////////////////////////////////////////////////////// -bool CAdEntity::setSprite(const char *filename) { - bool setCurrent = false; - if (_currentSprite == _sprite) { - _currentSprite = NULL; - setCurrent = true; - } - - delete _sprite; - _sprite = NULL; - CBSprite *spr = new CBSprite(_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/AdEntity.h b/engines/wintermute/ad/AdEntity.h deleted file mode 100644 index a260ca3329..0000000000 --- a/engines/wintermute/ad/AdEntity.h +++ /dev/null @@ -1,68 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/AdTalkHolder.h" - -namespace WinterMute { -class CVidTheoraPlayer; -class CAdEntity : public CAdTalkHolder { -public: - CVidTheoraPlayer *_theora; - bool setSprite(const char *filename); - int _walkToX; - int _walkToY; - TDirection _walkToDir; - void setItem(const char *itemName); - char *_item; - DECLARE_PERSISTENT(CAdEntity, CAdTalkHolder) - void updatePosition(); - virtual int getHeight(); - CBRegion *_region; - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - virtual bool update(); - virtual bool display(); - CAdEntity(CBGame *inGame); - virtual ~CAdEntity(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - TEntityType _subtype; - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdGame.cpp b/engines/wintermute/ad/AdGame.cpp deleted file mode 100644 index 87e3fe14d9..0000000000 --- a/engines/wintermute/ad/AdGame.cpp +++ /dev/null @@ -1,2061 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdActor.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/ad/AdEntity.h" -#include "engines/wintermute/ad/AdInventory.h" -#include "engines/wintermute/ad/AdInventoryBox.h" -#include "engines/wintermute/ad/AdItem.h" -#include "engines/wintermute/ad/AdResponse.h" -#include "engines/wintermute/ad/AdResponseBox.h" -#include "engines/wintermute/ad/AdResponseContext.h" -#include "engines/wintermute/ad/AdScene.h" -#include "engines/wintermute/ad/AdSceneState.h" -#include "engines/wintermute/ad/AdSentence.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/BObject.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/BSurfaceStorage.h" -#include "engines/wintermute/base/BTransitionMgr.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BViewport.h" -#include "engines/wintermute/base/particles/PartEmitter.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/ui/UIEntity.h" -#include "engines/wintermute/ui/UIWindow.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/video/VidPlayer.h" -#include "engines/wintermute/video/VidTheoraPlayer.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdGame, true) - -////////////////////////////////////////////////////////////////////////// -CAdGame::CAdGame(): CBGame() { - _responseBox = NULL; - _inventoryBox = NULL; - - _scene = new CAdScene(_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 CAdObject(this); - _inventoryOwner = _invObject; - - _tempDisableSaveState = false; - _itemsFile = NULL; - - _smartItemCursor = false; - - addSpeechDir("speech"); -} - - -////////////////////////////////////////////////////////////////////////// -CAdGame::~CAdGame() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::cleanup() { - int i; - - for (i = 0; i < _objects.getSize(); i++) { - unregisterObject(_objects[i]); - _objects[i] = NULL; - } - _objects.removeAll(); - - - for (i = 0; i < _dlgPendingBranches.getSize(); i++) { - delete [] _dlgPendingBranches[i]; - } - _dlgPendingBranches.removeAll(); - - for (i = 0; i < _speechDirs.getSize(); i++) { - delete [] _speechDirs[i]; - } - _speechDirs.removeAll(); - - - unregisterObject(_scene); - _scene = NULL; - - // remove items - for (i = 0; i < _items.getSize(); i++) _gameRef->unregisterObject(_items[i]); - _items.removeAll(); - - - // clear remaining inventories - delete _invObject; - _invObject = NULL; - - for (i = 0; i < _inventories.getSize(); i++) { - delete _inventories[i]; - } - _inventories.removeAll(); - - - 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 (i = 0; i < _sceneStates.getSize(); i++) delete _sceneStates[i]; - _sceneStates.removeAll(); - - for (i = 0; i < _responsesBranch.getSize(); i++) delete _responsesBranch[i]; - _responsesBranch.removeAll(); - - for (i = 0; i < _responsesGame.getSize(); i++) delete _responsesGame[i]; - _responsesGame.removeAll(); - - return CBGame::cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::initLoop() { - if (_scheduledScene && _transMgr->isReady()) { - changeScene(_scheduledScene, _scheduledFadeIn); - delete[] _scheduledScene; - _scheduledScene = NULL; - - _gameRef->_activeObject = NULL; - } - - - bool res; - res = CBGame::initLoop(); - if (DID_FAIL(res)) return res; - - if (_scene) res = _scene->initLoop(); - - _sentences.removeAll(); - - return res; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::addObject(CAdObject *object) { - _objects.add(object); - return registerObject(object); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::removeObject(CAdObject *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 (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i] == object) { - _objects.removeAt(i); - break; - } - } - return unregisterObject(object); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::changeScene(const char *filename, bool fadeIn) { - if (_scene == NULL) { - _scene = new CAdScene(_gameRef); - registerObject(_scene); - } else { - _scene->applyEvent("SceneShutdown", true); - - setPrevSceneName(_scene->_name); - setPrevSceneFilename(_scene->_filename); - - if (!_tempDisableSaveState) _scene->saveState(); - _tempDisableSaveState = false; - } - - if (_scene) { - // reset objects - for (int i = 0; i < _objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 CAdGame::addSentence(CAdSentence *sentence) { - _sentences.add(sentence); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::displaySentences(bool frozen) { - for (int i = 0; i < _sentences.getSize(); i++) { - if (frozen && _sentences[i]->_freezable) continue; - else _sentences[i]->display(); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CAdGame::finishSentences() { - for (int i = 0; i < _sentences.getSize(); i++) { - if (_sentences[i]->CanSkip()) { - _sentences[i]->_duration = 0; - if (_sentences[i]->_sound) _sentences[i]->_sound->stop(); - } - } -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CAdGame::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // ChangeScene - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "ChangeScene") == 0) { - stack->correctParams(3); - const char *filename = stack->pop()->getString(); - CScValue *valFadeOut = stack->pop(); - CScValue *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); - CAdActor *act = new CAdActor(_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); - CAdEntity *ent = new CAdEntity(_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); - CScValue *val = stack->pop(); - CAdObject *obj = (CAdObject *)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); - CScValue *val = stack->pop(); - - CAdEntity *ent = new CAdEntity(_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); - CScValue *val = stack->pop(); - - CAdItem *item = new CAdItem(_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); - CScValue *val = stack->pop(); - - CAdItem *item = NULL; - if (val->isNative()) item = (CAdItem *)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); - CScValue *val = stack->pop(); - - CAdItem *item = NULL; - if (val->isInt()) { - int index = val->getInt(); - if (index >= 0 && index < _items.getSize()) 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(); - CScValue *val1 = stack->pop(); - CScValue *val2 = stack->pop(); - CScValue *val3 = stack->pop(); - CScValue *val4 = stack->pop(); - - if (_responseBox) { - CAdResponse *res = new CAdResponse(_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.getSize() == 0) { - stack->pushNULL(); - return STATUS_OK; - } - - - if (_responseBox->_responses.getSize() == 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.getSize()); - } 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); - CScValue *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; - CScValue *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.getSize() > 0) { - stack->pushString(_dlgPendingBranches[_dlgPendingBranches.getSize() - 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); - - CScValue *val = stack->pop(); - if (!val->isNULL()) { - for (int i = 0; i < _inventories.getSize(); i++) { - CAdInventory *Inv = _inventories[i]; - - for (int j = 0; j < Inv->_takenItems.getSize(); j++) { - if (val->getNative() == Inv->_takenItems[j]) { - stack->pushBool(true); - return STATUS_OK; - } else if (scumm_stricmp(val->getString(), Inv->_takenItems[j]->_name) == 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 CAdResponseBox(_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 CAdInventoryBox(_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 CBViewport(_gameRef); - if (_sceneViewport) _sceneViewport->setRect(x, y, x + width, y + height); - - stack->pushBool(true); - - return STATUS_OK; - } - - - else return CBGame::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdGame::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.getSize()); - 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 CBGame::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::scSetProperty(const char *name, CScValue *value) { - - ////////////////////////////////////////////////////////////////////////// - // SelectedItem - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SelectedItem") == 0) { - if (value->isNULL()) _selectedItem = NULL; - else { - if (value->isNative()) { - _selectedItem = NULL; - for (int i = 0; i < _items.getSize(); i++) { - if (_items[i] == value->getNative()) { - _selectedItem = (CAdItem *)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 { - CBObject *Obj = (CBObject *)value->getNative(); - if (Obj == this) _inventoryOwner = _invObject; - else if (_gameRef->validObject(Obj)) _inventoryOwner = (CAdObject *)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 CBUtils::setString(&_startupScene, value->getString()); - - return STATUS_OK; - } - - else return CBGame::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name) { - CScValue *this_obj; - - ////////////////////////////////////////////////////////////////////////// - // Actor - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Actor") == 0) { - stack->correctParams(0); - this_obj = thisStack->getTop(); - - this_obj->setNative(new CAdActor(_gameRef)); - stack->pushNULL(); - } - - ////////////////////////////////////////////////////////////////////////// - // Entity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Entity") == 0) { - stack->correctParams(0); - this_obj = thisStack->getTop(); - - this_obj->setNative(new CAdEntity(_gameRef)); - stack->pushNULL(); - } - - - ////////////////////////////////////////////////////////////////////////// - // call parent - else return CBGame::ExternalCall(script, stack, thisStack, name); - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::showCursor() { - if (_cursorHidden) return STATUS_OK; - - if (_selectedItem && _gameRef->_state == GAME_RUNNING && _stateEx == GAME_NORMAL && _interactive) { - if (_selectedItem->_cursorCombined) { - CBSprite *origLastCursor = _lastCursor; - CBGame::showCursor(); - _lastCursor = origLastCursor; - } - if (_activeObject && _selectedItem->_cursorHover && _activeObject->getExtendedFlag("usable")) { - if (!_smartItemCursor || _activeObject->canHandleEvent(_selectedItem->_name)) - return drawCursor(_selectedItem->_cursorHover); - else - return drawCursor(_selectedItem->_cursorNormal); - } else return drawCursor(_selectedItem->_cursorNormal); - } else return CBGame::showCursor(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::loadFile(const char *filename) { - byte *buffer = _fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdGame::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdGame::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; - CBParser parser(_gameRef); - - 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(CBGame::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 CAdResponseBox(_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 CAdInventoryBox(_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; - CBUtils::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 CBViewport(_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: - CBUtils::setString(&_startupScene, (char *)params2); - break; - - case TOKEN_DEBUG_STARTUP_SCENE: - CBUtils::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 CAdGame::persist(CBPersistMgr *persistMgr) { - if (!persistMgr->_saving) cleanup(); - CBGame::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->_saving) _initialScene = false; - - persistMgr->transfer(TMEMBER(_startupScene)); - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::loadGame(const char *filename) { - bool ret = CBGame::loadGame(filename); - if (DID_SUCCEED(ret)) CSysClassRegistry::getInstance()->enumInstances(afterLoadRegion, "CAdRegion", NULL); - return ret; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::initAfterLoad() { - CBGame::initAfterLoad(); - CSysClassRegistry::getInstance()->enumInstances(afterLoadScene, "CAdScene", NULL); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CAdGame::afterLoadScene(void *scene, void *data) { - ((CAdScene *)scene)->afterLoad(); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdGame::setPrevSceneName(const char *name) { - delete[] _prevSceneName; - _prevSceneName = NULL; - if (name) { - _prevSceneName = new char[strlen(name) + 1]; - if (_prevSceneName) strcpy(_prevSceneName, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -void CAdGame::setPrevSceneFilename(const char *name) { - delete[] _prevSceneFilename; - _prevSceneFilename = NULL; - if (name) { - _prevSceneFilename = new char[strlen(name) + 1]; - if (_prevSceneFilename) strcpy(_prevSceneFilename, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::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 CAdGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor) { - CBGame::getVersion(verMajor, verMinor, NULL, NULL); - - if (extMajor) *extMajor = 0; - if (extMinor) *extMinor = 0; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::loadItemsFile(const char *filename, bool merge) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdGame::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 CAdGame::loadItemsBuffer(byte *buffer, bool merge) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ITEM) - TOKEN_TABLE_END - - byte *params; - int cmd; - CBParser parser(_gameRef); - - if (!merge) { - while (_items.getSize() > 0) deleteItem(_items[0]); - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_ITEM: { - CAdItem *item = new CAdItem(_gameRef); - if (item && !DID_FAIL(item->loadBuffer(params, false))) { - // delete item with the same name, if exists - if (merge) { - CAdItem *PrevItem = getItemByName(item->_name); - 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; -} - - -////////////////////////////////////////////////////////////////////////// -CAdSceneState *CAdGame::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 (int i = 0; i < _sceneStates.getSize(); i++) { - if (scumm_stricmp(_sceneStates[i]->_filename, filenameCor) == 0) { - delete [] filenameCor; - return _sceneStates[i]; - } - } - - if (saving) { - CAdSceneState *ret = new CAdSceneState(_gameRef); - ret->setFilename(filenameCor); - - _sceneStates.add(ret); - - delete [] filenameCor; - return ret; - } else { - delete [] filenameCor; - return NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::windowLoadHook(CUIWindow *win, char **buffer, char **params) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ENTITY_CONTAINER) - TOKEN_TABLE_END - - int cmd = PARSERR_GENERIC; - CBParser parser(_gameRef); - - cmd = parser.getCommand(buffer, commands, params); - switch (cmd) { - case TOKEN_ENTITY_CONTAINER: { - CUIEntity *ent = new CUIEntity(_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 CAdGame::windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name) { - if (strcmp(name, "CreateEntityContainer") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - - CUIEntity *ent = new CUIEntity(_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 CAdGame::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 CAdGame::endDlgBranch(const char *branchName, const char *scriptName, const char *eventName) { - char *name = NULL; - bool deleteName = false; - if (branchName == NULL && _dlgPendingBranches.getSize() > 0) { - name = _dlgPendingBranches[_dlgPendingBranches.getSize() - 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.getSize() - 1; i >= 0; i--) { - if (scumm_stricmp(name, _dlgPendingBranches[i]) == 0) { - startIndex = i; - break; - } - } - if (startIndex >= 0) { - for (int i = startIndex; i < _dlgPendingBranches.getSize(); i++) { - //ClearBranchResponses(_dlgPendingBranches[i]); - delete [] _dlgPendingBranches[i]; - _dlgPendingBranches[i] = NULL; - } - _dlgPendingBranches.removeAt(startIndex, _dlgPendingBranches.getSize() - startIndex); - } - - // dialogue is over, forget selected responses - if (_dlgPendingBranches.getSize() == 0) { - for (int i = 0; i < _responsesBranch.getSize(); i++) delete _responsesBranch[i]; - _responsesBranch.removeAll(); - } - - if (deleteName) delete [] name; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::clearBranchResponses(char *name) { - for (int i = 0; i < _responsesBranch.getSize(); i++) { - if (scumm_stricmp(name, _responsesBranch[i]->_context) == 0) { - delete _responsesBranch[i]; - _responsesBranch.removeAt(i); - i--; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::addBranchResponse(int ID) { - if (branchResponseUsed(ID)) return STATUS_OK; - CAdResponseContext *r = new CAdResponseContext(_gameRef); - r->_iD = ID; - r->setContext(_dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL); - _responsesBranch.add(r); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::branchResponseUsed(int ID) { - char *Context = _dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL; - for (int i = 0; i < _responsesBranch.getSize(); 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 CAdGame::addGameResponse(int ID) { - if (gameResponseUsed(ID)) return STATUS_OK; - CAdResponseContext *r = new CAdResponseContext(_gameRef); - r->_iD = ID; - r->setContext(_dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL); - _responsesGame.add(r); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::gameResponseUsed(int ID) { - char *Context = _dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL; - for (int i = 0; i < _responsesGame.getSize(); i++) { - CAdResponseContext *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 CAdGame::resetResponse(int ID) { - char *Context = _dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL; - - int i; - - for (i = 0; i < _responsesGame.getSize(); i++) { - if (_responsesGame[i]->_iD == ID) { - if ((Context == NULL && _responsesGame[i]->_context == NULL) || scumm_stricmp(Context, _responsesGame[i]->_context) == 0) { - delete _responsesGame[i]; - _responsesGame.removeAt(i); - break; - } - } - } - - for (i = 0; i < _responsesBranch.getSize(); i++) { - if (_responsesBranch[i]->_iD == ID) { - if ((Context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(Context, _responsesBranch[i]->_context) == 0) { - delete _responsesBranch[i]; - _responsesBranch.removeAt(i); - break; - } - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::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(); - if (_indicatorDisplay) 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 CAdGame::registerInventory(CAdInventory *inv) { - for (int i = 0; i < _inventories.getSize(); i++) { - if (_inventories[i] == inv) return STATUS_OK; - } - registerObject(inv); - _inventories.add(inv); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::unregisterInventory(CAdInventory *inv) { - for (int i = 0; i < _inventories.getSize(); i++) { - if (_inventories[i] == inv) { - unregisterObject(_inventories[i]); - _inventories.removeAt(i); - return STATUS_OK; - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::isItemTaken(char *itemName) { - for (int i = 0; i < _inventories.getSize(); i++) { - CAdInventory *Inv = _inventories[i]; - - for (int j = 0; j < Inv->_takenItems.getSize(); j++) { - if (scumm_stricmp(itemName, Inv->_takenItems[j]->_name) == 0) { - return true; - } - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -CAdItem *CAdGame::getItemByName(const char *name) { - for (int i = 0; i < _items.getSize(); i++) { - if (scumm_stricmp(_items[i]->_name, name) == 0) return _items[i]; - } - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::addItem(CAdItem *item) { - _items.add(item); - return _gameRef->registerObject(item); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::resetContent() { - // clear pending dialogs - for (int i = 0; i < _dlgPendingBranches.getSize(); i++) { - delete [] _dlgPendingBranches[i]; - } - _dlgPendingBranches.removeAll(); - - - // clear inventories - for (int i = 0; i < _inventories.getSize(); i++) { - _inventories[i]->_takenItems.removeAll(); - } - - // clear scene states - for (int i = 0; i < _sceneStates.getSize(); i++) delete _sceneStates[i]; - _sceneStates.removeAll(); - - // clear once responses - for (int i = 0; i < _responsesBranch.getSize(); i++) delete _responsesBranch[i]; - _responsesBranch.removeAll(); - - // clear once game responses - for (int i = 0; i < _responsesGame.getSize(); i++) delete _responsesGame[i]; - _responsesGame.removeAll(); - - // reload inventory items - if (_itemsFile) loadItemsFile(_itemsFile); - - _tempDisableSaveState = true; - - return CBGame::resetContent(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::deleteItem(CAdItem *item) { - if (!item) return STATUS_FAILED; - - if (_selectedItem == item) _selectedItem = NULL; - _scene->handleItemAssociations(item->_name, false); - - // remove from all inventories - for (int i = 0; i < _inventories.getSize(); i++) { - _inventories[i]->removeItem(item); - } - - // remove object - for (int i = 0; i < _items.getSize(); i++) { - if (_items[i] == item) { - unregisterObject(_items[i]); - _items.removeAt(i); - break; - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::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 (int i = 0; i < _speechDirs.getSize(); i++) { - if (scumm_stricmp(_speechDirs[i], temp) == 0) { - delete [] temp; - return STATUS_OK; - } - } - _speechDirs.add(temp); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::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 (int i = 0; i < _speechDirs.getSize(); i++) { - if (scumm_stricmp(_speechDirs[i], temp) == 0) { - delete [] _speechDirs[i]; - _speechDirs.removeAt(i); - Found = true; - break; - } - } - delete [] temp; - - if (Found) return STATUS_OK; - else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -char *CAdGame::findSpeechFile(char *stringID) { - char *ret = new char[MAX_PATH_LENGTH]; - - for (int i = 0; i < _speechDirs.getSize(); i++) { - sprintf(ret, "%s%s.ogg", _speechDirs[i], stringID); - Common::SeekableReadStream *file = _fileManager->openFile(ret); // TODO: Replace with hasFile - if (file) { - _fileManager->closeFile(file); - return ret; - } - - sprintf(ret, "%s%s.wav", _speechDirs[i], stringID); - file = _fileManager->openFile(ret); - if (file) { - _fileManager->closeFile(file); - return ret; - } - } - delete [] ret; - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::validMouse() { - Point32 pos; - CBPlatform::getCursorPos(&pos); - - return _renderer->pointInViewport(&pos); -} - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::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; - CBPlatform::setCapture(/*_renderer->_window*/); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::onMouseLeftUp() { - if (_activeObject) _activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT); - - CBPlatform::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 CAdGame::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 CAdGame::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 CAdGame::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 CAdGame::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->_name) ? _scene->_name : "???", _prevSceneName ? _prevSceneName : "???"); - _systemFont->drawText((byte *)str, 0, 110, _renderer->_width, TAL_RIGHT); - } - return CBGame::displayDebugInfo(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdGame::onScriptShutdown(CScScript *script) { - if (_responseBox && _responseBox->_waitingScript == script) - _responseBox->_waitingScript = NULL; - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdGame.h b/engines/wintermute/ad/AdGame.h deleted file mode 100644 index 4a89fa97d2..0000000000 --- a/engines/wintermute/ad/AdGame.h +++ /dev/null @@ -1,161 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/AdTypes.h" -#include "engines/wintermute/base/BGame.h" - -namespace WinterMute { -class CAdItem; -class CAdInventory; -class CAdSceneState; -class CAdScene; -class CAdItem; -class CAdObject; -class CAdSentence; -class CAdInventoryBox; -class CAdResponseContext; -class CAdResponseBox; -class CAdGame : public CBGame { -public: - virtual bool onScriptShutdown(CScScript *script); - - virtual bool onMouseLeftDown(); - virtual bool onMouseLeftUp(); - virtual bool onMouseLeftDblClick(); - virtual bool onMouseRightDown(); - virtual bool onMouseRightUp(); - - virtual bool displayDebugInfo(); - - - virtual bool initAfterLoad(); - static void afterLoadScene(void *scene, void *data); - - bool _smartItemCursor; - - CBArray _speechDirs; - bool addSpeechDir(const char *dir); - bool removeSpeechDir(const char *dir); - char *findSpeechFile(char *StringID); - - bool deleteItem(CAdItem *Item); - char *_itemsFile; - bool _tempDisableSaveState; - virtual bool resetContent(); - bool addItem(CAdItem *item); - CAdItem *getItemByName(const char *name); - CBArray _items; - CAdObject *_inventoryOwner; - bool isItemTaken(char *itemName); - bool registerInventory(CAdInventory *inv); - bool unregisterInventory(CAdInventory *inv); - - CAdObject *_invObject; - CBArray _inventories; - virtual bool displayContent(bool update = true, bool displayAll = false); - char *_debugStartupScene; - char *_startupScene; - bool _initialScene; - 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(CUIWindow *win, char **buf, char **params); - virtual bool windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name); - - CAdSceneState *getSceneState(const char *filename, bool saving); - CBViewport *_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); - char *_scheduledScene; - bool _scheduledFadeIn; - void setPrevSceneName(const char *name); - void setPrevSceneFilename(const char *name); - char *_prevSceneName; - char *_prevSceneFilename; - virtual bool loadGame(const char *filename); - CAdItem *_selectedItem; - bool cleanup(); - DECLARE_PERSISTENT(CAdGame, CBGame) - - void finishSentences(); - bool showCursor(); - TGameStateEx _stateEx; - CAdResponseBox *_responseBox; - CAdInventoryBox *_inventoryBox; - bool displaySentences(bool frozen); - void addSentence(CAdSentence *sentence); - bool changeScene(const char *filename, bool fadeIn); - bool removeObject(CAdObject *object); - bool addObject(CAdObject *object); - CAdScene *_scene; - bool initLoop(); - CAdGame(); - virtual ~CAdGame(); - CBArray _objects; - CBArray _sentences; - - CBArray _sceneStates; - CBArray _dlgPendingBranches; - - CBArray _responsesBranch; - CBArray _responsesGame; - - 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); - - - virtual bool ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - bool validMouse(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdInventory.cpp b/engines/wintermute/ad/AdInventory.cpp deleted file mode 100644 index f913108404..0000000000 --- a/engines/wintermute/ad/AdInventory.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/AdInventory.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/ad/AdItem.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdInventory, false) - -////////////////////////////////////////////////////////////////////////// -CAdInventory::CAdInventory(CBGame *inGame): CBObject(inGame) { - _scrollOffset = 0; -} - - -////////////////////////////////////////////////////////////////////////// -CAdInventory::~CAdInventory() { - _takenItems.removeAll(); // ref only -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdInventory::insertItem(const char *name, const char *insertAfter) { - if (name == NULL) return STATUS_FAILED; - - CAdItem *item = ((CAdGame *)_gameRef)->getItemByName(name); - if (item == NULL) return STATUS_FAILED; - - int insertIndex = -1; - for (int i = 0; i < _takenItems.getSize(); i++) { - if (scumm_stricmp(_takenItems[i]->_name, name) == 0) { - _takenItems.removeAt(i); - i--; - continue; - } - if (insertAfter && scumm_stricmp(_takenItems[i]->_name, insertAfter) == 0) insertIndex = i + 1; - } - - - if (insertIndex == -1) _takenItems.add(item); - else _takenItems.insertAt(insertIndex, item); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdInventory::removeItem(const char *name) { - if (name == NULL) return STATUS_FAILED; - - for (int i = 0; i < _takenItems.getSize(); i++) { - if (scumm_stricmp(_takenItems[i]->_name, name) == 0) { - if (((CAdGame *)_gameRef)->_selectedItem == _takenItems[i])((CAdGame *)_gameRef)->_selectedItem = NULL; - _takenItems.removeAt(i); - return STATUS_OK; - } - } - - return STATUS_FAILED; -} - - - -////////////////////////////////////////////////////////////////////////// -bool CAdInventory::removeItem(CAdItem *item) { - if (item == NULL) return STATUS_FAILED; - - for (int i = 0; i < _takenItems.getSize(); i++) { - if (_takenItems[i] == item) { - if (((CAdGame *)_gameRef)->_selectedItem == _takenItems[i])((CAdGame *)_gameRef)->_selectedItem = NULL; - _takenItems.removeAt(i); - return STATUS_OK; - } - } - - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdInventory::persist(CBPersistMgr *persistMgr) { - - CBObject::persist(persistMgr); - - _takenItems.persist(persistMgr); - persistMgr->transfer(TMEMBER(_scrollOffset)); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdInventory.h b/engines/wintermute/ad/AdInventory.h deleted file mode 100644 index cec76c03a0..0000000000 --- a/engines/wintermute/ad/AdInventory.h +++ /dev/null @@ -1,52 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" - -namespace WinterMute { - -class CAdItem; - -class CAdInventory : public CBObject { -public: - DECLARE_PERSISTENT(CAdInventory, CBObject) - bool removeItem(const char *name); - bool removeItem(CAdItem *Item); - bool insertItem(const char *name, const char *insertAfter = NULL); - CAdInventory(CBGame *inGame); - virtual ~CAdInventory(); - CBArray _takenItems; - int _scrollOffset; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdInventoryBox.cpp b/engines/wintermute/ad/AdInventoryBox.cpp deleted file mode 100644 index 9509bf9b10..0000000000 --- a/engines/wintermute/ad/AdInventoryBox.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdGame.h" -#include "engines/wintermute/ad/AdInventoryBox.h" -#include "engines/wintermute/ad/AdInventory.h" -#include "engines/wintermute/ad/AdItem.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/BViewport.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/ui/UIButton.h" -#include "engines/wintermute/ui/UIWindow.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" -#include "common/rect.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdInventoryBox, false) - -////////////////////////////////////////////////////////////////////////// -CAdInventoryBox::CAdInventoryBox(CBGame *inGame): CBObject(inGame) { - _itemsArea.setEmpty(); - _scrollOffset = 0; - _spacing = 0; - _itemWidth = _itemHeight = 50; - _scrollBy = 1; - - _window = NULL; - _closeButton = NULL; - - _hideSelected = false; - - _visible = false; - _exclusive = false; -} - - -////////////////////////////////////////////////////////////////////////// -CAdInventoryBox::~CAdInventoryBox() { - _gameRef->unregisterObject(_window); - _window = NULL; - - delete _closeButton; - _closeButton = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdInventoryBox::listen(CBScriptHolder *param1, uint32 param2) { - CUIObject *obj = (CUIObject *)param1; - - switch (obj->_type) { - case UI_BUTTON: - if (scumm_stricmp(obj->_name, "close") == 0) { - _visible = false; - } else if (scumm_stricmp(obj->_name, "prev") == 0) { - _scrollOffset -= _scrollBy; - _scrollOffset = MAX(_scrollOffset, 0); - } else if (scumm_stricmp(obj->_name, "next") == 0) { - _scrollOffset += _scrollBy; - } else return CBObject::listen(param1, param2); - break; - default: - error("CAdInventoryBox::Listen - Unhandled enum"); - break; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdInventoryBox::display() { - CAdGame *adGame = (CAdGame *)_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 < adGame->_inventoryOwner->getInventory()->_takenItems.getSize()); - } - - - 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 < adGame->_inventoryOwner->getInventory()->_takenItems.getSize()) { - CAdItem *item = adGame->_inventoryOwner->getInventory()->_takenItems[itemIndex]; - if (item != ((CAdGame *)_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 CAdInventoryBox::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdInventoryBox::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdInventoryBox::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; - CBParser parser(_gameRef); - bool always_visible = 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 CUIWindow(_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", &always_visible); - 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 CUIButton(_gameRef); - if (_closeButton) { - _closeButton->setName("close"); - _closeButton->setListener(this, _closeButton, 0); - _closeButton->_parent = _window; - } - } - - _visible = always_visible; - - if (_window) { - for (int i = 0; i < _window->_widgets.getSize(); i++) { - if (!_window->_widgets[i]->_listenerObject) - _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdInventoryBox::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "INVENTORY_BOX\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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 - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdInventoryBox::persist(CBPersistMgr *persistMgr) { - CBObject::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/AdInventoryBox.h b/engines/wintermute/ad/AdInventoryBox.h deleted file mode 100644 index cfd8d74021..0000000000 --- a/engines/wintermute/ad/AdInventoryBox.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" -#include "common/rect.h" - -namespace WinterMute { -class CUIButton; -class CUIWindow; - -class CAdInventoryBox : public CBObject { -public: - bool _hideSelected; - DECLARE_PERSISTENT(CAdInventoryBox, CBObject) - bool _exclusive; - int _scrollBy; - int _itemHeight; - int _itemWidth; - bool _visible; - virtual bool display(); - CUIButton *_closeButton; - int _spacing; - int _scrollOffset; - Rect32 _itemsArea; - bool listen(CBScriptHolder *param1, uint32 param2); - CUIWindow *_window; - CAdInventoryBox(CBGame *inGame); - virtual ~CAdInventoryBox(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdItem.cpp b/engines/wintermute/ad/AdItem.cpp deleted file mode 100644 index 0e443d5c3e..0000000000 --- a/engines/wintermute/ad/AdItem.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdItem.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/ad/AdSentence.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdItem, false) - -////////////////////////////////////////////////////////////////////////// -CAdItem::CAdItem(CBGame *inGame): CAdTalkHolder(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; -} - - -////////////////////////////////////////////////////////////////////////// -CAdItem::~CAdItem() { - delete _spriteHover; - delete _cursorNormal; - delete _cursorHover; - _spriteHover = NULL; - _cursorNormal = NULL; - _cursorHover = NULL; - - delete[] _amountString; - _amountString = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdItem::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdItem::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdItem::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; - CBParser parser(_gameRef); - - 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 CBSprite(_gameRef, this); - if (!_sprite || DID_FAIL(_sprite->loadFile((char *)params, ((CAdGame *)_gameRef)->_texItemLifeTime))) { - delete _sprite; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE_HOVER: - case TOKEN_SPRITE_HOVER: - delete _spriteHover; - _spriteHover = new CBSprite(_gameRef, this); - if (!_spriteHover || DID_FAIL(_spriteHover->loadFile((char *)params, ((CAdGame *)_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: - CBUtils::setString(&_amountString, (char *)params); - break; - - case TOKEN_TALK: { - CBSprite *spr = new CBSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params, ((CAdGame *)_gameRef)->_texTalkLifeTime))) cmd = PARSERR_GENERIC; - else _talkSprites.add(spr); - } - break; - - case TOKEN_TALK_SPECIAL: { - CBSprite *spr = new CBSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params, ((CAdGame *)_gameRef)->_texTalkLifeTime))) cmd = PARSERR_GENERIC; - else _talkSpritesEx.add(spr); - } - break; - - case TOKEN_CURSOR: - delete _cursorNormal; - _cursorNormal = new CBSprite(_gameRef); - if (!_cursorNormal || DID_FAIL(_cursorNormal->loadFile((char *)params, ((CAdGame *)_gameRef)->_texItemLifeTime))) { - delete _cursorNormal; - _cursorNormal = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_CURSOR_HOVER: - delete _cursorHover; - _cursorHover = new CBSprite(_gameRef); - if (!_cursorHover || DID_FAIL(_cursorHover->loadFile((char *)params, ((CAdGame *)_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 CAdItem::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; - } - ((CAdGame *)_gameRef)->addSentence(_sentence); - } - } else { - _currentSprite = _tempSprite2; - ((CAdGame *)_gameRef)->addSentence(_sentence); - } - } - default: - break; - } - _ready = (_state == STATE_READY); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdItem::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; - - CBFont *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 CAdItem::scCallMethod(CScScript *script, CScStack *stack, CScStack *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; - CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_spriteHover->_filename); - 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; - CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_cursorNormal->_filename); - 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; - CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_cursorHover->_filename); - 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 CAdTalkHolder::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdItem::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(_name); - 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 CAdTalkHolder::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdItem::scSetProperty(const char *name, CScValue *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 { - CBUtils::setString(&_amountString, value->getString()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorCombined - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorCombined") == 0) { - _cursorCombined = value->getBool(); - return STATUS_OK; - } - - else return CAdTalkHolder::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdItem::scToString() { - return "[item]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdItem::persist(CBPersistMgr *persistMgr) { - - CAdTalkHolder::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 CAdItem::getExtendedFlag(const char *flagName) { - if (!flagName) return false; - else if (strcmp(flagName, "usable") == 0) return true; - else return CAdObject::getExtendedFlag(flagName); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdItem.h b/engines/wintermute/ad/AdItem.h deleted file mode 100644 index d45f9cc614..0000000000 --- a/engines/wintermute/ad/AdItem.h +++ /dev/null @@ -1,70 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/AdTalkHolder.h" - -namespace WinterMute { - -class CAdItem : public CAdTalkHolder { -public: - bool _displayAmount; - int _amount; - int _amountOffsetX; - int _amountOffsetY; - TTextAlign _amountAlign; - char *_amountString; - - - bool update(); - DECLARE_PERSISTENT(CAdItem, CAdTalkHolder) - bool display(int x, int y); - bool getExtendedFlag(const char *flagName); - bool _inInventory; - bool _cursorCombined; - CBSprite *_spriteHover; - CBSprite *_cursorNormal; - CBSprite *_cursorHover; - CAdItem(CBGame *inGame); - virtual ~CAdItem(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdLayer.cpp b/engines/wintermute/ad/AdLayer.cpp deleted file mode 100644 index 4549ba4af7..0000000000 --- a/engines/wintermute/ad/AdLayer.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/ad/AdLayer.h" -#include "engines/wintermute/ad/AdSceneNode.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdLayer, false) - -////////////////////////////////////////////////////////////////////////// -CAdLayer::CAdLayer(CBGame *inGame): CBObject(inGame) { - _main = false; - _width = _height = 0; - _active = true; - _closeUp = false; -} - - -////////////////////////////////////////////////////////////////////////// -CAdLayer::~CAdLayer() { - for (int i = 0; i < _nodes.getSize(); i++) - delete _nodes[i]; - _nodes.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdLayer::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdLayer::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdLayer::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; - CBParser parser(_gameRef); - - 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: { - CAdRegion *region = new CAdRegion(_gameRef); - CAdSceneNode *node = new CAdSceneNode(_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: { - CAdEntity *entity = new CAdEntity(_gameRef); - CAdSceneNode *node = new CAdSceneNode(_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 CAdLayer::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // GetNode - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GetNode") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - int node = -1; - - if (val->_type == VAL_INT) node = val->getInt(); - else { // get by name - for (int i = 0; i < _nodes.getSize(); i++) { - if ((_nodes[i]->_type == OBJECT_ENTITY && scumm_stricmp(_nodes[i]->_entity->_name, val->getString()) == 0) || - (_nodes[i]->_type == OBJECT_REGION && scumm_stricmp(_nodes[i]->_region->_name, val->getString()) == 0)) { - node = i; - break; - } - } - } - - if (node < 0 || node >= _nodes.getSize()) 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); - CScValue *val = stack->pop(); - - CAdSceneNode *node = new CAdSceneNode(_gameRef); - if (strcmp(name, "AddRegion") == 0) { - CAdRegion *region = new CAdRegion(_gameRef); - if (!val->isNULL()) region->setName(val->getString()); - node->setRegion(region); - stack->pushNative(region, true); - } else { - CAdEntity *entity = new CAdEntity(_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(); - CScValue *val = stack->pop(); - - CAdSceneNode *node = new CAdSceneNode(_gameRef); - if (strcmp(name, "InsertRegion") == 0) { - CAdRegion *region = new CAdRegion(_gameRef); - if (!val->isNULL()) region->setName(val->getString()); - node->setRegion(region); - stack->pushNative(region, true); - } else { - CAdEntity *entity = new CAdEntity(_gameRef); - if (!val->isNULL()) entity->setName(val->getString()); - node->setEntity(entity); - stack->pushNative(entity, true); - } - if (index < 0) index = 0; - if (index <= _nodes.getSize() - 1) _nodes.insertAt(index, node); - else _nodes.add(node); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DeleteNode - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DeleteNode") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - - CAdSceneNode *toDelete = NULL; - if (val->isNative()) { - CBScriptable *temp = val->getNative(); - for (int i = 0; i < _nodes.getSize(); i++) { - if (_nodes[i]->_region == temp || _nodes[i]->_entity == temp) { - toDelete = _nodes[i]; - break; - } - } - } else { - int index = val->getInt(); - if (index >= 0 && index < _nodes.getSize()) { - toDelete = _nodes[index]; - } - } - if (toDelete == NULL) { - stack->pushBool(false); - return STATUS_OK; - } - - for (int i = 0; i < _nodes.getSize(); i++) { - if (_nodes[i] == toDelete) { - delete _nodes[i]; - _nodes[i] = NULL; - _nodes.removeAt(i); - break; - } - } - stack->pushBool(true); - return STATUS_OK; - } - - else return CBObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdLayer::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.getSize()); - 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 CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdLayer::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdLayer::scToString() { - return "[layer]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdLayer::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "LAYER {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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"); - - int i; - - for (i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - if (_scProp) _scProp->saveAsText(buffer, indent + 2); - - for (i = 0; i < _nodes.getSize(); 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("CAdLayer::SaveAsText - Unhandled enum"); - break; - } - } - - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdLayer::persist(CBPersistMgr *persistMgr) { - - CBObject::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/AdLayer.h b/engines/wintermute/ad/AdLayer.h deleted file mode 100644 index 0ccdb13ae7..0000000000 --- a/engines/wintermute/ad/AdLayer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CAdSceneNode; -class CAdLayer : public CBObject { -public: - bool _closeUp; - DECLARE_PERSISTENT(CAdLayer, CBObject) - bool _active; - int _height; - int _width; - bool _main; - CAdLayer(CBGame *inGame); - virtual ~CAdLayer(); - CBArray _nodes; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdNodeState.cpp b/engines/wintermute/ad/AdNodeState.cpp deleted file mode 100644 index fd72a356c5..0000000000 --- a/engines/wintermute/ad/AdNodeState.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/ad/AdNodeState.h" -#include "engines/wintermute/ad/AdEntity.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdNodeState, false) - - -////////////////////////////////////////////////////////////////////////// -CAdNodeState::CAdNodeState(CBGame *inGame): CBBase(inGame) { - _name = NULL; - _active = false; - for (int i = 0; i < 7; i++) _caption[i] = NULL; - _alphaColor = 0; - _filename = NULL; - _cursor = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdNodeState::~CAdNodeState() { - 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 CAdNodeState::setName(const char *name) { - delete[] _name; - _name = NULL; - CBUtils::setString(&_name, name); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdNodeState::setFilename(const char *filename) { - delete[] _filename; - _filename = NULL; - CBUtils::setString(&_filename, filename); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdNodeState::setCursor(const char *filename) { - delete[] _cursor; - _cursor = NULL; - CBUtils::setString(&_cursor, filename); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdNodeState::persist(CBPersistMgr *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 CAdNodeState::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]); - } -} - - -////////////////////////////////////////////////////////////////////////// -char *CAdNodeState::getCaption(int caseVal) { - if (caseVal== 0) caseVal= 1; - if (caseVal< 1 || caseVal> 7 || _caption[caseVal- 1] == NULL) return ""; - else return _caption[caseVal- 1]; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdNodeState::transferEntity(CAdEntity *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->_filename) { - if (includingSprites) setFilename(entity->_sprite->_filename); - else setFilename(""); - } - if (entity->_cursor && entity->_cursor->_filename) setCursor(entity->_cursor->_filename); - _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->_filename || scumm_stricmp(entity->_sprite->_filename, _filename) != 0) - entity->setSprite(_filename); - } - if (_cursor) { - if (!entity->_cursor || !entity->_cursor->_filename || scumm_stricmp(entity->_cursor->_filename, _cursor) != 0) - entity->setCursor(_cursor); - } - - entity->_active = _active; - entity->_alphaColor = _alphaColor; - } - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdNodeState.h b/engines/wintermute/ad/AdNodeState.h deleted file mode 100644 index 186f2ebbb2..0000000000 --- a/engines/wintermute/ad/AdNodeState.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CAdEntity; - -class CAdNodeState : public CBBase { -public: - bool transferEntity(CAdEntity *entity, bool includingSprites, bool saving); - void setName(const char *name); - void setFilename(const char *filename); - void setCursor(const char *filename); - DECLARE_PERSISTENT(CAdNodeState, CBBase) - CAdNodeState(CBGame *inGame); - virtual ~CAdNodeState(); - char *_name; - bool _active; - char *_caption[7]; - void setCaption(const char *caption, int caseVal); - char *getCaption(int caseVal); - uint32 _alphaColor; - char *_filename; - char *_cursor; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdObject.cpp b/engines/wintermute/ad/AdObject.cpp deleted file mode 100644 index c74c8cf6b3..0000000000 --- a/engines/wintermute/ad/AdObject.cpp +++ /dev/null @@ -1,1203 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdGame.h" -#include "engines/wintermute/ad/AdItem.h" -#include "engines/wintermute/ad/AdObject.h" -#include "engines/wintermute/ad/AdInventory.h" -#include "engines/wintermute/ad/AdLayer.h" -#include "engines/wintermute/ad/AdScene.h" -#include "engines/wintermute/ad/AdSceneNode.h" -#include "engines/wintermute/ad/AdSentence.h" -#include "engines/wintermute/ad/AdWaypointGroup.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFrame.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BSurfaceStorage.h" -#include "engines/wintermute/base/BSubFrame.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "common/str.h" -#include "common/util.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdObject, false) - -////////////////////////////////////////////////////////////////////////// -CAdObject::CAdObject(CBGame *inGame): CBObject(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; -} - - -////////////////////////////////////////////////////////////////////////// -CAdObject::~CAdObject() { - _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) { - ((CAdGame *)_gameRef)->unregisterInventory(_inventory); - _inventory = NULL; - } - - if (_partEmitter) - _gameRef->unregisterObject(_partEmitter); - - - for (int i = 0; i < _attachmentsPre.getSize(); i++) { - _gameRef->unregisterObject(_attachmentsPre[i]); - } - _attachmentsPre.removeAll(); - - for (int i = 0; i < _attachmentsPost.getSize(); i++) { - _gameRef->unregisterObject(_attachmentsPost[i]); - } - _attachmentsPost.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::playAnim(const char *filename) { - delete _animSprite; - _animSprite = NULL; - _animSprite = new CBSprite(_gameRef, this); - if (!_animSprite) { - _gameRef->LOG(0, "CAdObject::PlayAnim: error creating temp sprite (object:\"%s\" sprite:\"%s\")", _name, filename); - return STATUS_FAILED; - } - bool res = _animSprite->loadFile(filename); - if (DID_FAIL(res)) { - _gameRef->LOG(res, "CAdObject::PlayAnim: error loading temp sprite (object:\"%s\" sprite:\"%s\")", _name, filename); - delete _animSprite; - _animSprite = NULL; - return res; - } - _state = STATE_PLAYING_ANIM; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::display() { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::update() { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CAdObject::scCallMethod(CScScript *script, CScStack *stack, CScStack *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(); - CScValue *soundVal = stack->pop(); - int duration = stack->pop()->getInt(); - CScValue *valStances = stack->pop(); - - const char *stances = valStances->isNULL() ? NULL : valStances->getString(); - - int align = 0; - CScValue *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); - - CAdLayer *main = ((CAdGame *)_gameRef)->_scene->_mainLayer; - bool regFound = false; - - int i; - CScValue *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.getSize(); i++) { - if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region->_name && scumm_stricmp(main->_nodes[i]->_region->_name, regionName) == 0) { - _stickRegion = main->_nodes[i]->_region; - regFound = true; - break; - } - } - } else if (val->isNative()) { - CBScriptable *obj = val->getNative(); - - for (i = 0; i < main->_nodes.getSize(); 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); - CScValue *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->_filename) stack->pushString(_font->_filename); - else stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TakeItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TakeItem") == 0) { - stack->correctParams(2); - - if (!_inventory) { - _inventory = new CAdInventory(_gameRef); - ((CAdGame *)_gameRef)->registerInventory(_inventory); - } - - CScValue *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 - ((CAdGame *)_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 CAdInventory(_gameRef); - ((CAdGame *)_gameRef)->registerInventory(_inventory); - } - - CScValue *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 - ((CAdGame *)_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 CAdInventory(_gameRef); - ((CAdGame *)_gameRef)->registerInventory(_inventory); - } - - CScValue *val = stack->pop(); - if (val->_type == VAL_STRING) { - CAdItem *item = ((CAdGame *)_gameRef)->getItemByName(val->getString()); - if (item) stack->pushNative(item, true); - else stack->pushNULL(); - } else if (val->isNULL() || val->getInt() < 0 || val->getInt() >= _inventory->_takenItems.getSize()) - 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 CAdInventory(_gameRef); - ((CAdGame *)_gameRef)->registerInventory(_inventory); - } - - CScValue *val = stack->pop(); - if (!val->isNULL()) { - for (int i = 0; i < _inventory->_takenItems.getSize(); i++) { - if (val->getNative() == _inventory->_takenItems[i]) { - stack->pushBool(true); - return STATUS_OK; - } else if (scumm_stricmp(val->getString(), _inventory->_takenItems[i]->_name) == 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(); - - CPartEmitter *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; - CAdEntity *ent = new CAdEntity(_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); - CScValue *val = stack->pop(); - bool found = false; - if (val->isNative()) { - CBScriptable *obj = val->getNative(); - for (int i = 0; i < _attachmentsPre.getSize(); i++) { - if (_attachmentsPre[i] == obj) { - found = true; - _gameRef->unregisterObject(_attachmentsPre[i]); - _attachmentsPre.removeAt(i); - i--; - } - } - for (int i = 0; i < _attachmentsPost.getSize(); i++) { - if (_attachmentsPost[i] == obj) { - found = true; - _gameRef->unregisterObject(_attachmentsPost[i]); - _attachmentsPost.removeAt(i); - i--; - } - } - } else { - const char *attachmentName = val->getString(); - for (int i = 0; i < _attachmentsPre.getSize(); i++) { - if (_attachmentsPre[i]->_name && scumm_stricmp(_attachmentsPre[i]->_name, attachmentName) == 0) { - found = true; - _gameRef->unregisterObject(_attachmentsPre[i]); - _attachmentsPre.removeAt(i); - i--; - } - } - for (int i = 0; i < _attachmentsPost.getSize(); i++) { - if (_attachmentsPost[i]->_name && scumm_stricmp(_attachmentsPost[i]->_name, attachmentName) == 0) { - found = true; - _gameRef->unregisterObject(_attachmentsPost[i]); - _attachmentsPost.removeAt(i); - i--; - } - } - } - stack->pushBool(found); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetAttachment - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetAttachment") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - - CAdObject *ret = NULL; - if (val->isInt()) { - int index = val->getInt(); - int currIndex = 0; - for (int i = 0; i < _attachmentsPre.getSize(); i++) { - if (currIndex == index) ret = _attachmentsPre[i]; - currIndex++; - } - for (int i = 0; i < _attachmentsPost.getSize(); i++) { - if (currIndex == index) ret = _attachmentsPost[i]; - currIndex++; - } - } else { - const char *attachmentName = val->getString(); - for (int i = 0; i < _attachmentsPre.getSize(); i++) { - if (_attachmentsPre[i]->_name && scumm_stricmp(_attachmentsPre[i]->_name, attachmentName) == 0) { - ret = _attachmentsPre[i]; - break; - } - } - if (!ret) { - for (int i = 0; i < _attachmentsPost.getSize(); i++) { - if (_attachmentsPost[i]->_name && scumm_stricmp(_attachmentsPost[i]->_name, attachmentName) == 0) { - ret = _attachmentsPre[i]; - break; - } - } - } - } - - if (ret != NULL) stack->pushNative(ret, true); - else stack->pushNULL(); - - return STATUS_OK; - } - - else return CBObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdObject::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.getSize()); - 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.getSize() + _attachmentsPost.getSize()); - return _scValue; - } - - - else return CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdObject::scToString() { - return "[ad object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::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 CAdObject::getHeight() { - if (!_currentSprite) return 0; - else { - CBFrame *frame = _currentSprite->_frames[_currentSprite->_currentFrame]; - int ret = 0; - for (int i = 0; i < frame->_subframes.getSize(); i++) { - ret = MAX(ret, frame->_subframes[i]->_hotspotY); - } - - if (_zoomable) { - float zoom = ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY); - ret = (int)(ret * zoom / 100); - } - return ret; - } -} - - -////////////////////////////////////////////////////////////////////////// -void CAdObject::talk(const char *text, const char *sound, uint32 duration, const char *stances, TTextAlign Align) { - if (!_sentence) _sentence = new CAdSentence(_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 = ((CAdGame *)_gameRef)->findSpeechFile(key); - delete [] key; - - if (sound) deleteSound = true; - } - } - - // load sound and set duration appropriately - if (sound) { - CBSound *snd = new CBSound(_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 -= ((CAdGame *)_gameRef)->_scene->getOffsetLeft(); - y -= ((CAdGame *)_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 += ((CAdGame *)_gameRef)->_scene->getOffsetLeft(); - _sentence->_pos.y += ((CAdGame *)_gameRef)->_scene->getOffsetTop(); - } - - _sentence->_fixedPos = !_subtitlesModRelative; - - - _sentence->setupTalkFile(sound); - - _state = STATE_TALKING; - - if (deleteSound) delete [] sound; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::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 CAdObject::persist(CBPersistMgr *persistMgr) { - CBObject::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 CAdObject::updateSounds() { - if (_sentence && _sentence->_sound) - updateOneSound(_sentence->_sound); - - return CBObject::updateSounds(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::resetSoundPan() { - if (_sentence && _sentence->_sound) { - _sentence->_sound->setPan(0.0f); - } - return CBObject::resetSoundPan(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::getExtendedFlag(const char *flagName) { - if (!flagName) return false; - else if (strcmp(flagName, "usable") == 0) return true; - - else return CBObject::getExtendedFlag(flagName); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::saveAsText(CBDynBuffer *buffer, int indent) { - if (_blockRegion) _blockRegion->saveAsText(buffer, indent + 2, "BLOCKED_REGION"); - if (_wptGroup) _wptGroup->saveAsText(buffer, indent + 2); - - CBBase::saveAsText(buffer, indent + 2); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::updateBlockRegion() { - CAdGame *adGame = (CAdGame *)_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; -} - -////////////////////////////////////////////////////////////////////////// -CAdInventory *CAdObject::getInventory() { - if (!_inventory) { - _inventory = new CAdInventory(_gameRef); - ((CAdGame *)_gameRef)->registerInventory(_inventory); - } - return _inventory; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::afterMove() { - CAdRegion *newRegions[MAX_NUM_REGIONS]; - - ((CAdGame *)_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 CAdObject::invalidateCurrRegions() { - for (int i = 0; i < MAX_NUM_REGIONS; i++) _currentRegions[i] = NULL; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::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 = ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) + _relativeScale; - } else { - *scaleX = *scaleY = 100; - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::updateSpriteAttachments() { - for (int i = 0; i < _attachmentsPre.getSize(); i++) { - _attachmentsPre[i]->update(); - } - for (int i = 0; i < _attachmentsPost.getSize(); i++) { - _attachmentsPost[i]->update(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::displaySpriteAttachments(bool preDisplay) { - if (preDisplay) { - for (int i = 0; i < _attachmentsPre.getSize(); i++) { - displaySpriteAttachment(_attachmentsPre[i]); - } - } else { - for (int i = 0; i < _attachmentsPost.getSize(); i++) { - displaySpriteAttachment(_attachmentsPost[i]); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::displaySpriteAttachment(CAdObject *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; -} - -////////////////////////////////////////////////////////////////////////// -CPartEmitter *CAdObject::createParticleEmitter(bool followParent, int offsetX, int offsetY) { - _partFollowParent = followParent; - _partOffsetX = offsetX; - _partOffsetY = offsetY; - - if (!_partEmitter) { - _partEmitter = new CPartEmitter(_gameRef, this); - if (_partEmitter) { - _gameRef->registerObject(_partEmitter); - } - } - updatePartEmitter(); - return _partEmitter; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdObject::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/AdObject.h b/engines/wintermute/ad/AdObject.h deleted file mode 100644 index d662e84729..0000000000 --- a/engines/wintermute/ad/AdObject.h +++ /dev/null @@ -1,123 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/AdTypes.h" -#include "engines/wintermute/base/particles/PartEmitter.h" - -namespace WinterMute { - -class CAdWaypointGroup; -class CAdRegion; -class CAdSentence; -class CBFont; -class CBRegion; -class CAdInventory; - -#define MAX_NUM_REGIONS 10 - -class CAdObject : public CBObject { -public: - CPartEmitter *_partEmitter; - virtual CPartEmitter *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; - CAdRegion *_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(CAdObject, CBObject) - virtual void talk(const char *text, const char *sound = NULL, uint32 duration = 0, const char *stances = NULL, TTextAlign align = TAL_CENTER); - virtual int getHeight(); - CAdSentence *_sentence; - bool SetFont(const char *filename); - virtual bool update(); - virtual bool display(); - bool _drawn; - bool _active; - virtual bool playAnim(const char *filename); - CBSprite *_animSprite; - CBSprite *_currentSprite; - TObjectState _state; - TObjectState _nextState; - TObjectType _type; - CAdObject(CBGame *inGame); - virtual ~CAdObject(); - CBFont *_font; - CBSprite *_tempSprite2; - CBRegion *_blockRegion; - CAdWaypointGroup *_wptGroup; - CBRegion *_currentBlockRegion; - CAdWaypointGroup *_currentWptGroup; - CAdInventory *getInventory(); - - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - virtual bool afterMove(); - CAdRegion *_currentRegions[MAX_NUM_REGIONS]; - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - - CBArray _attachmentsPre; - CBArray _attachmentsPost; - - bool updateSpriteAttachments(); - bool displaySpriteAttachments(bool preDisplay); - CAdObject *_registerAlias; -private: - bool displaySpriteAttachment(CAdObject *attachment); - CAdInventory *_inventory; - -protected: - bool getScale(float *scaleX, float *scaleY); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdPath.cpp b/engines/wintermute/ad/AdPath.cpp deleted file mode 100644 index d1b9d87063..0000000000 --- a/engines/wintermute/ad/AdPath.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdPath.h" -#include "engines/wintermute/base/BPoint.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdPath, false) - -////////////////////////////////////////////////////////////////////////// -CAdPath::CAdPath(CBGame *inGame): CBBase(inGame) { - _currIndex = -1; - _ready = false; -} - - -////////////////////////////////////////////////////////////////////////// -CAdPath::~CAdPath() { - reset(); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdPath::reset() { - for (int i = 0; i < _points.getSize(); i++) - delete _points[i]; - - _points.removeAll(); - _currIndex = -1; - _ready = false; -} - - -////////////////////////////////////////////////////////////////////////// -CBPoint *CAdPath::getFirst() { - if (_points.getSize() > 0) { - _currIndex = 0; - return _points[_currIndex]; - } else return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CBPoint *CAdPath::getNext() { - _currIndex++; - if (_currIndex < _points.getSize()) return _points[_currIndex]; - else return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CBPoint *CAdPath::getCurrent() { - if (_currIndex >= 0 && _currIndex < _points.getSize()) return _points[_currIndex]; - else return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void CAdPath::addPoint(CBPoint *point) { - _points.add(point); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdPath::setReady(bool ready) { - bool orig = _ready; - _ready = ready; - - return orig; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdPath::persist(CBPersistMgr *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/AdPath.h b/engines/wintermute/ad/AdPath.h deleted file mode 100644 index fdc2980042..0000000000 --- a/engines/wintermute/ad/AdPath.h +++ /dev/null @@ -1,56 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" - -namespace WinterMute { -class CBPoint; -class CAdPath : public CBBase { -public: - DECLARE_PERSISTENT(CAdPath, CBBase) - CBPoint *getCurrent(); - bool setReady(bool ready = true); - void addPoint(CBPoint *point); - CBPoint *getNext(); - CBPoint *getFirst(); - void reset(); - CAdPath(CBGame *inGame); - virtual ~CAdPath(); - CBArray _points; - int _currIndex; - bool _ready; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdPathPoint.cpp b/engines/wintermute/ad/AdPathPoint.cpp deleted file mode 100644 index 184ad8559a..0000000000 --- a/engines/wintermute/ad/AdPathPoint.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/AdPathPoint.h" -#include "engines/wintermute/base/BPersistMgr.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdPathPoint, false) - -////////////////////////////////////////////////////////////////////////// -CAdPathPoint::CAdPathPoint() { - x = y = 0; - _distance = 0; - - _marked = false; - _origin = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdPathPoint::CAdPathPoint(int initX, int initY, int initDistance) { - x = initX; - y = initY; - _distance = initDistance; - - _marked = false; - _origin = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdPathPoint::~CAdPathPoint() { - _origin = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdPathPoint::persist(CBPersistMgr *persistMgr) { - - CBPoint::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/AdPathPoint.h b/engines/wintermute/ad/AdPathPoint.h deleted file mode 100644 index f58df765b1..0000000000 --- a/engines/wintermute/ad/AdPathPoint.h +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BPoint.h" - -namespace WinterMute { - -class CAdPathPoint : public CBPoint { -public: - DECLARE_PERSISTENT(CAdPathPoint, CBPoint) - CAdPathPoint(int initX, int initY, int initDistance); - CAdPathPoint(); - virtual ~CAdPathPoint(); - CAdPathPoint *_origin; - bool _marked; - int _distance; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdRegion.cpp b/engines/wintermute/ad/AdRegion.cpp deleted file mode 100644 index a1864de1ac..0000000000 --- a/engines/wintermute/ad/AdRegion.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdRegion.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdRegion, false) - -////////////////////////////////////////////////////////////////////////// -CAdRegion::CAdRegion(CBGame *inGame): CBRegion(inGame) { - _blocked = false; - _decoration = false; - _zoom = 0; - _alpha = 0xFFFFFFFF; -} - - -////////////////////////////////////////////////////////////////////////// -CAdRegion::~CAdRegion() { -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdRegion::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdRegion::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdRegion::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; - CBParser parser(_gameRef); - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_REGION) { - _gameRef->LOG(0, "'REGION' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - for (int i = 0; i < _points.getSize(); i++) delete _points[i]; - _points.removeAll(); - - 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 CBPoint(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 CAdRegion::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CBRegion::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdRegion::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(_name); - 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 CBRegion::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdRegion::scSetProperty(const char *name, CScValue *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 CBRegion::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdRegion::scToString() { - return "[ad region]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdRegion::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "REGION {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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"); - - int i; - for (i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - if (_scProp) _scProp->saveAsText(buffer, indent + 2); - - for (i = 0; i < _points.getSize(); i++) { - buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); - } - - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdRegion::persist(CBPersistMgr *persistMgr) { - CBRegion::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/AdRegion.h b/engines/wintermute/ad/AdRegion.h deleted file mode 100644 index c91feb4012..0000000000 --- a/engines/wintermute/ad/AdRegion.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BRegion.h" - -namespace WinterMute { - -class CAdRegion : public CBRegion { -public: - DECLARE_PERSISTENT(CAdRegion, CBRegion) - uint32 _alpha; - float _zoom; - bool _blocked; - bool _decoration; - CAdRegion(CBGame *inGame); - virtual ~CAdRegion(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdResponse.cpp b/engines/wintermute/ad/AdResponse.cpp deleted file mode 100644 index 20617f9573..0000000000 --- a/engines/wintermute/ad/AdResponse.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdResponse.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/utils/utils.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdResponse, false) - -////////////////////////////////////////////////////////////////////////// -CAdResponse::CAdResponse(CBGame *inGame): CBObject(inGame) { - _text = NULL; - _textOrig = NULL; - _icon = _iconHover = _iconPressed = NULL; - _font = NULL; - _iD = 0; - _responseType = RESPONSE_ALWAYS; -} - - -////////////////////////////////////////////////////////////////////////// -CAdResponse::~CAdResponse() { - 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 CAdResponse::setText(const char *text) { - CBUtils::setString(&_text, text); - CBUtils::setString(&_textOrig, text); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponse::setIcon(const char *filename) { - delete _icon; - _icon = new CBSprite(_gameRef); - if (!_icon || DID_FAIL(_icon->loadFile(filename))) { - _gameRef->LOG(0, "CAdResponse::setIcon failed for file '%s'", filename); - delete _icon; - _icon = NULL; - return STATUS_FAILED; - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdResponse::setFont(const char *filename) { - if (_font) _gameRef->_fontStorage->removeFont(_font); - _font = _gameRef->_fontStorage->addFont(filename); - if (!_font) { - _gameRef->LOG(0, "CAdResponse::setFont failed for file '%s'", filename); - return STATUS_FAILED; - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdResponse::setIconHover(const char *filename) { - delete _iconHover; - _iconHover = new CBSprite(_gameRef); - if (!_iconHover || DID_FAIL(_iconHover->loadFile(filename))) { - _gameRef->LOG(0, "CAdResponse::setIconHover failed for file '%s'", filename); - delete _iconHover; - _iconHover = NULL; - return STATUS_FAILED; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponse::setIconPressed(const char *filename) { - delete _iconPressed; - _iconPressed = new CBSprite(_gameRef); - if (!_iconPressed || DID_FAIL(_iconPressed->loadFile(filename))) { - _gameRef->LOG(0, "CAdResponse::setIconPressed failed for file '%s'", filename); - delete _iconPressed; - _iconPressed = NULL; - return STATUS_FAILED; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponse::persist(CBPersistMgr *persistMgr) { - - CBObject::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/AdResponse.h b/engines/wintermute/ad/AdResponse.h deleted file mode 100644 index 646d781b89..0000000000 --- a/engines/wintermute/ad/AdResponse.h +++ /dev/null @@ -1,61 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" -#include "engines/wintermute/ad/AdTypes.h" - -namespace WinterMute { -class CBFont; -class CAdResponse : public CBObject { -public: - DECLARE_PERSISTENT(CAdResponse, CBObject) - 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; - CBSprite *_icon; - CBSprite *_iconHover; - CBSprite *_iconPressed; - CBFont *_font; - char *_text; - char *_textOrig; - CAdResponse(CBGame *inGame); - virtual ~CAdResponse(); - TResponseType _responseType; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdResponseBox.cpp b/engines/wintermute/ad/AdResponseBox.cpp deleted file mode 100644 index 829d58f2ee..0000000000 --- a/engines/wintermute/ad/AdResponseBox.cpp +++ /dev/null @@ -1,647 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdGame.h" -#include "engines/wintermute/ad/AdResponseBox.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BSurfaceStorage.h" -#include "engines/wintermute/ui/UIButton.h" -#include "engines/wintermute/ui/UIWindow.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/ad/AdResponse.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdResponseBox, false) - -////////////////////////////////////////////////////////////////////////// -CAdResponseBox::CAdResponseBox(CBGame *inGame): CBObject(inGame) { - _font = _fontHover = NULL; - - _window = NULL; - _shieldWindow = new CUIWindow(_gameRef); - - _horizontal = false; - CBPlatform::setRectEmpty(&_responseArea); - _scrollOffset = 0; - _spacing = 0; - - _waitingScript = NULL; - _lastResponseText = NULL; - _lastResponseTextOrig = NULL; - - _verticalAlign = VAL_BOTTOM; - _align = TAL_LEFT; -} - - -////////////////////////////////////////////////////////////////////////// -CAdResponseBox::~CAdResponseBox() { - - 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 CAdResponseBox::clearResponses() { - for (int i = 0; i < _responses.getSize(); i++) { - delete _responses[i]; - } - _responses.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdResponseBox::clearButtons() { - for (int i = 0; i < _respButtons.getSize(); i++) { - delete _respButtons[i]; - } - _respButtons.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseBox::invalidateButtons() { - for (int i = 0; i < _respButtons.getSize(); 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 CAdResponseBox::createButtons() { - clearButtons(); - - _scrollOffset = 0; - for (int i = 0; i < _responses.getSize(); i++) { - CUIButton *btn = new CUIButton(_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 CAdResponseBox::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdResponseBox::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdResponseBox::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; - CBParser parser(_gameRef); - - 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 CUIWindow(_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 CBSprite(_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 (int i = 0; i < _window->_widgets.getSize(); i++) { - if (!_window->_widgets[i]->_listenerObject) - _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseBox::saveAsText(CBDynBuffer *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->_filename) - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); - if (_fontHover && _fontHover->_filename) - buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->_filename); - - if (_cursor && _cursor->_filename) - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); - - 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("CAdResponseBox::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 - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseBox::display() { - Rect32 rect = _responseArea; - if (_window) { - CBPlatform::offsetRect(&rect, _window->_posX, _window->_posY); - //_window->display(); - } - - int xxx, yyy, i; - - xxx = rect.left; - yyy = rect.top; - - // shift down if needed - if (!_horizontal) { - int total_height = 0; - for (i = 0; i < _respButtons.getSize(); i++) total_height += (_respButtons[i]->_height + _spacing); - total_height -= _spacing; - - switch (_verticalAlign) { - case VAL_BOTTOM: - if (yyy + total_height < rect.bottom) - yyy = rect.bottom - total_height; - break; - - case VAL_CENTER: - if (yyy + total_height < rect.bottom) - yyy += ((rect.bottom - rect.top) - total_height) / 2; - break; - - case VAL_TOP: - // do nothing - break; - } - } - - // prepare response buttons - bool scrollNeeded = false; - for (i = _scrollOffset; i < _respButtons.getSize(); 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.getSize(); i++) { - _respButtons[i]->display(); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseBox::listen(CBScriptHolder *param1, uint32 param2) { - CUIObject *obj = (CUIObject *)param1; - - switch (obj->_type) { - case UI_BUTTON: - if (scumm_stricmp(obj->_name, "prev") == 0) { - _scrollOffset--; - } else if (scumm_stricmp(obj->_name, "next") == 0) { - _scrollOffset++; - } else if (scumm_stricmp(obj->_name, "response") == 0) { - if (_waitingScript) _waitingScript->_stack->pushInt(_responses[param2]->_iD); - handleResponse(_responses[param2]); - _waitingScript = NULL; - _gameRef->_state = GAME_RUNNING; - ((CAdGame *)_gameRef)->_stateEx = GAME_NORMAL; - _ready = true; - invalidateButtons(); - clearResponses(); - } else return CBObject::listen(param1, param2); - break; - default: - error("AdResponseBox::Listen - Unhandled enum"); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseBox::persist(CBPersistMgr *persistMgr) { - CBObject::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 CAdResponseBox::weedResponses() { - CAdGame *adGame = (CAdGame *)_gameRef; - - for (int i = 0; i < _responses.getSize(); i++) { - switch (_responses[i]->_responseType) { - case RESPONSE_ONCE: - if (adGame->branchResponseUsed(_responses[i]->_iD)) { - delete _responses[i]; - _responses.removeAt(i); - i--; - } - break; - - case RESPONSE_ONCE_GAME: - if (adGame->gameResponseUsed(_responses[i]->_iD)) { - delete _responses[i]; - _responses.removeAt(i); - i--; - } - break; - default: - warning("CAdResponseBox::WeedResponses - Unhandled enum"); - break; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CAdResponseBox::setLastResponseText(const char *text, const char *textOrig) { - CBUtils::setString(&_lastResponseText, text); - CBUtils::setString(&_lastResponseTextOrig, textOrig); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseBox::handleResponse(CAdResponse *response) { - setLastResponseText(response->_text, response->_textOrig); - - CAdGame *adGame = (CAdGame *)_gameRef; - - switch (response->_responseType) { - case RESPONSE_ONCE: - adGame->addBranchResponse(response->_iD); - break; - - case RESPONSE_ONCE_GAME: - adGame->addGameResponse(response->_iD); - break; - default: - warning("CAdResponseBox::HandleResponse - Unhandled enum"); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CBObject *CAdResponseBox::getNextAccessObject(CBObject *currObject) { - CBArray objects; - getObjects(objects, true); - - if (objects.getSize() == 0) return NULL; - else { - if (currObject != NULL) { - for (int i = 0; i < objects.getSize(); i++) { - if (objects[i] == currObject) { - if (i < objects.getSize() - 1) return objects[i + 1]; - else break; - } - } - } - return objects[0]; - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -CBObject *CAdResponseBox::getPrevAccessObject(CBObject *currObject) { - CBArray objects; - getObjects(objects, true); - - if (objects.getSize() == 0) return NULL; - else { - if (currObject != NULL) { - for (int i = objects.getSize() - 1; i >= 0; i--) { - if (objects[i] == currObject) { - if (i > 0) return objects[i - 1]; - else break; - } - } - } - return objects[objects.getSize() - 1]; - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseBox::getObjects(CBArray &objects, bool interactiveOnly) { - for (int i = 0; i < _respButtons.getSize(); i++) { - objects.add(_respButtons[i]); - } - if (_window) _window->getWindowObjects(objects, interactiveOnly); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdResponseBox.h b/engines/wintermute/ad/AdResponseBox.h deleted file mode 100644 index 93b677bd4a..0000000000 --- a/engines/wintermute/ad/AdResponseBox.h +++ /dev/null @@ -1,87 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" - -namespace WinterMute { - -class CUIButton; -class CUIWindow; -class CUIObject; -class CAdResponse; -class CAdResponseBox : public CBObject { -public: - CBObject *getNextAccessObject(CBObject *CurrObject); - CBObject *getPrevAccessObject(CBObject *CurrObject); - bool getObjects(CBArray &objects, bool interactiveOnly); - - bool handleResponse(CAdResponse *response); - void setLastResponseText(const char *text, const char *textOrig); - char *_lastResponseText; - char *_lastResponseTextOrig; - DECLARE_PERSISTENT(CAdResponseBox, CBObject) - CScScript *_waitingScript; - virtual bool listen(CBScriptHolder *param1, uint32 param2); - typedef enum { - EVENT_PREV, - EVENT_NEXT, - EVENT_RESPONSE - } TResponseEvent; - - bool weedResponses(); - bool display(); - int _spacing; - int _scrollOffset; - CBFont *_fontHover; - CBFont *_font; - bool createButtons(); - bool invalidateButtons(); - void clearButtons(); - void clearResponses(); - CAdResponseBox(CBGame *inGame); - virtual ~CAdResponseBox(); - CBArray _responses; - CBArray _respButtons; - CUIWindow *_window; - CUIWindow *_shieldWindow; - bool _horizontal; - Rect32 _responseArea; - int _verticalAlign; - TTextAlign _align; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdResponseContext.cpp b/engines/wintermute/ad/AdResponseContext.cpp deleted file mode 100644 index 8573e58b95..0000000000 --- a/engines/wintermute/ad/AdResponseContext.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdResponseContext.h" -#include "engines/wintermute/base/BPersistMgr.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdResponseContext, false) - -////////////////////////////////////////////////////////////////////////// -CAdResponseContext::CAdResponseContext(CBGame *inGame): CBBase(inGame) { - _iD = 0; - _context = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdResponseContext::~CAdResponseContext() { - delete[] _context; - _context = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdResponseContext::persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_gameRef)); - persistMgr->transfer(TMEMBER(_context)); - persistMgr->transfer(TMEMBER(_iD)); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CAdResponseContext::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/AdResponseContext.h b/engines/wintermute/ad/AdResponseContext.h deleted file mode 100644 index 74506405de..0000000000 --- a/engines/wintermute/ad/AdResponseContext.h +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" - -namespace WinterMute { - -class CAdResponseContext : public CBBase { -public: - void setContext(const char *context); - int _iD; - char *_context; - DECLARE_PERSISTENT(CAdResponseContext, CBBase) - CAdResponseContext(CBGame *inGame); - virtual ~CAdResponseContext(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdRotLevel.cpp b/engines/wintermute/ad/AdRotLevel.cpp deleted file mode 100644 index 671d003f35..0000000000 --- a/engines/wintermute/ad/AdRotLevel.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdRotLevel.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdRotLevel, false) - - -////////////////////////////////////////////////////////////////////////// -CAdRotLevel::CAdRotLevel(CBGame *inGame): CBObject(inGame) { - _posX = 0; - _rotation = 0.0f; -} - - -////////////////////////////////////////////////////////////////////////// -CAdRotLevel::~CAdRotLevel() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdRotLevel::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdRotLevel::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdRotLevel::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; - CBParser parser(_gameRef); - - 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 CAdRotLevel::saveAsText(CBDynBuffer *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); - CBBase::saveAsText(buffer, indent + 2); - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdRotLevel::persist(CBPersistMgr *persistMgr) { - - CBObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_rotation)); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdRotLevel.h b/engines/wintermute/ad/AdRotLevel.h deleted file mode 100644 index 9e536a8d8f..0000000000 --- a/engines/wintermute/ad/AdRotLevel.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" - -namespace WinterMute { - -class CAdRotLevel : public CBObject { -public: - DECLARE_PERSISTENT(CAdRotLevel, CBObject) - CAdRotLevel(CBGame *inGame); - virtual ~CAdRotLevel(); - float _rotation; - virtual bool saveAsText(CBDynBuffer *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/AdScaleLevel.cpp b/engines/wintermute/ad/AdScaleLevel.cpp deleted file mode 100644 index 1ac2f7ba6c..0000000000 --- a/engines/wintermute/ad/AdScaleLevel.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdScaleLevel.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdScaleLevel, false) - -////////////////////////////////////////////////////////////////////////// -CAdScaleLevel::CAdScaleLevel(CBGame *inGame): CBObject(inGame) { - _posY = 0; - _scale = 100; -} - - -////////////////////////////////////////////////////////////////////////// -CAdScaleLevel::~CAdScaleLevel() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScaleLevel::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdScaleLevel::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdScaleLevel::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; - CBParser parser(_gameRef); - - 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 CAdScaleLevel::saveAsText(CBDynBuffer *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); - CBBase::saveAsText(buffer, indent + 2); - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScaleLevel::persist(CBPersistMgr *persistMgr) { - - CBObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_scale)); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdScaleLevel.h b/engines/wintermute/ad/AdScaleLevel.h deleted file mode 100644 index c360ec4eff..0000000000 --- a/engines/wintermute/ad/AdScaleLevel.h +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" - -namespace WinterMute { - -class CAdScaleLevel : public CBObject { -public: - DECLARE_PERSISTENT(CAdScaleLevel, CBObject) - float _scale; - CAdScaleLevel(CBGame *inGame); - virtual ~CAdScaleLevel(); - virtual bool saveAsText(CBDynBuffer *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/AdScene.cpp b/engines/wintermute/ad/AdScene.cpp deleted file mode 100644 index b284543a08..0000000000 --- a/engines/wintermute/ad/AdScene.cpp +++ /dev/null @@ -1,2752 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/AdScene.h" -#include "engines/wintermute/ad/AdActor.h" -#include "engines/wintermute/ad/AdEntity.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/ad/AdLayer.h" -#include "engines/wintermute/ad/AdNodeState.h" -#include "engines/wintermute/ad/AdObject.h" -#include "engines/wintermute/ad/AdPath.h" -#include "engines/wintermute/ad/AdPathPoint.h" -#include "engines/wintermute/ad/AdRotLevel.h" -#include "engines/wintermute/ad/AdScaleLevel.h" -#include "engines/wintermute/ad/AdSceneNode.h" -#include "engines/wintermute/ad/AdSceneState.h" -#include "engines/wintermute/ad/AdSentence.h" -#include "engines/wintermute/ad/AdWaypointGroup.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BObject.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BPoint.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/base/BScriptable.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BViewport.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/ui/UIWindow.h" -#include "engines/wintermute/utils/utils.h" -#include - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdScene, false) - -////////////////////////////////////////////////////////////////////////// -CAdScene::CAdScene(CBGame *inGame): CBObject(inGame) { - _pfTarget = new CBPoint; - setDefaults(); -} - - -////////////////////////////////////////////////////////////////////////// -CAdScene::~CAdScene() { - cleanup(); - _gameRef->unregisterObject(_fader); - delete _pfTarget; - _pfTarget = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void CAdScene::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 CBFader(_gameRef); - _gameRef->registerObject(_fader); - - _viewport = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void CAdScene::cleanup() { - CBObject::cleanup(); - - _mainLayer = NULL; // reference only - - int i; - - delete _shieldWindow; - _shieldWindow = NULL; - - _gameRef->unregisterObject(_fader); - _fader = NULL; - - for (i = 0; i < _layers.getSize(); i++) - _gameRef->unregisterObject(_layers[i]); - _layers.removeAll(); - - - for (i = 0; i < _waypointGroups.getSize(); i++) - _gameRef->unregisterObject(_waypointGroups[i]); - _waypointGroups.removeAll(); - - for (i = 0; i < _scaleLevels.getSize(); i++) - _gameRef->unregisterObject(_scaleLevels[i]); - _scaleLevels.removeAll(); - - for (i = 0; i < _rotLevels.getSize(); i++) - _gameRef->unregisterObject(_rotLevels[i]); - _rotLevels.removeAll(); - - - for (i = 0; i < _pfPath.getSize(); i++) - delete _pfPath[i]; - _pfPath.removeAll(); - _pfPointsNum = 0; - - for (i = 0; i < _objects.getSize(); i++) - _gameRef->unregisterObject(_objects[i]); - _objects.removeAll(); - - delete _viewport; - _viewport = NULL; - - setDefaults(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::getPath(CBPoint source, CBPoint target, CAdPath *path, CBObject *requester) { - if (!_pfReady) return false; - else { - _pfReady = false; - *_pfTarget = target; - _pfTargetPath = path; - _pfRequester = requester; - - _pfTargetPath->reset(); - _pfTargetPath->setReady(false); - - // prepare working path - int i; - pfPointsStart(); - - // first point - //_pfPath.add(new CAdPathPoint(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 CAdPathPoint(target.x, target.y, INT_MAX)); - pfPointsAdd(target.x, target.y, INT_MAX); - - // active waypoints - for (i = 0; i < _waypointGroups.getSize(); i++) { - if (_waypointGroups[i]->_active) { - pfAddWaypointGroup(_waypointGroups[i], requester); - } - } - - - // free waypoints - for (i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentWptGroup) { - pfAddWaypointGroup(_objects[i]->_currentWptGroup, requester); - } - } - CAdGame *adGame = (CAdGame *)_gameRef; - for (i = 0; i < adGame->_objects.getSize(); i++) { - if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentWptGroup) { - pfAddWaypointGroup(adGame->_objects[i]->_currentWptGroup, requester); - } - } - - return true; - } -} - - -////////////////////////////////////////////////////////////////////////// -void CAdScene::pfAddWaypointGroup(CAdWaypointGroup *wpt, CBObject *requester) { - if (!wpt->_active) return; - - for (int i = 0; i < wpt->_points.getSize(); i++) { - if (isBlockedAt(wpt->_points[i]->x, wpt->_points[i]->y, true, requester)) continue; - - //_pfPath.add(new CAdPathPoint(Wpt->_points[i]->x, Wpt->_points[i]->y, INT_MAX)); - pfPointsAdd(wpt->_points[i]->x, wpt->_points[i]->y, INT_MAX); - } -} - - -////////////////////////////////////////////////////////////////////////// -float CAdScene::getZoomAt(int x, int y) { - float ret = 100; - - bool found = false; - if (_mainLayer) { - for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) { - CAdSceneNode *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 CAdScene::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.getSize() - 1; i >= 0; i--) { - CAdSceneNode *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 CAdScene::isBlockedAt(int x, int y, bool checkFreeObjects, CBObject *requester) { - bool ret = true; - - - if (checkFreeObjects) { - for (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { - if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) return true; - } - } - CAdGame *adGame = (CAdGame *)_gameRef; - for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _mainLayer->_nodes.getSize(); i++) { - CAdSceneNode *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 CAdScene::isWalkableAt(int x, int y, bool checkFreeObjects, CBObject *requester) { - bool ret = false; - - if (checkFreeObjects) { - for (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { - if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) return false; - } - } - CAdGame *adGame = (CAdGame *)_gameRef; - for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _mainLayer->_nodes.getSize(); i++) { - CAdSceneNode *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 CAdScene::getPointsDist(CBPoint p1, CBPoint p2, CBObject *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) { - CBUtils::swap(&x1, &x2); - CBUtils::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) { - CBUtils::swap(&x1, &x2); - CBUtils::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 CAdScene::pathFinderStep() { - int i; - // get lowest unmarked - int lowestDist = INT_MAX; - CAdPathPoint *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.insertAt(0, new CBPoint(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 CAdScene::initLoop() { -#ifdef _DEBUGxxxx - int nu_steps = 0; - uint32 start = _gameRef->_currentTime; - while (!_pfReady && CBPlatform::getTime() - 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 && CBPlatform::getTime() - start <= _pfMaxTime) pathFinderStep(); -#endif - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdScene::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - delete[] _filename; - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, filename); - - if (DID_FAIL(ret = loadBuffer(buffer, true))) _gameRef->LOG(0, "Error parsing SCENE file '%s'", filename); - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdScene::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; - CBParser parser(_gameRef); - - 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: { - CAdLayer *layer = new CAdLayer(_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: { - CAdWaypointGroup *wpt = new CAdWaypointGroup(_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: { - CAdScaleLevel *sl = new CAdScaleLevel(_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: { - CAdRotLevel *rl = new CAdRotLevel(_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: { - CAdEntity *entity = new CAdEntity(_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 CBSprite(_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 CBViewport(_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.", _filename); - - - sortScaleLevels(); - sortRotLevels(); - - _initialized = true; - - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::traverseNodes(bool doUpdate) { - if (!_initialized) return STATUS_OK; - - int j, k; - CAdGame *adGame = (CAdGame *)_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 (j = 0; j < _layers.getSize(); j++) { - if (!_layers[j]->_active) continue; - - // make layer exclusive - if (!doUpdate) { - if (_layers[j]->_closeUp && !_gameRef->_editorMode) { - if (!_shieldWindow) _shieldWindow = new CUIWindow(_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 (k = 0; k < _layers[j]->_nodes.getSize(); k++) { - CAdSceneNode *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 CAdScene::display() { - return traverseNodes(false); -} - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::updateFreeObjects() { - CAdGame *adGame = (CAdGame *)_gameRef; - bool is3DSet; - - // *** update all active objects - is3DSet = false; - for (int i = 0; i < adGame->_objects.getSize(); i++) { - if (!adGame->_objects[i]->_active) continue; - - adGame->_objects[i]->update(); - adGame->_objects[i]->_drawn = false; - } - - - for (int i = 0; i < _objects.getSize(); 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 CAdScene::displayRegionContent(CAdRegion *region, bool display3DOnly) { - CAdGame *adGame = (CAdGame *)_gameRef; - CBArray objects; - CAdObject *obj; - - // global objects - for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 - qsort(objects.getData(), objects.getSize(), sizeof(CAdObject *), CAdScene::compareObjs); - - // display them - for (int i = 0; i < objects.getSize(); 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 (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_active && _objects[i]->_editorOnly) { - _objects[i]->display(); - _objects[i]->_drawn = true; - } - } - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -int CAdScene::compareObjs(const void *obj1, const void *obj2) { - CAdObject *object1 = *(CAdObject **)obj1; - CAdObject *object2 = *(CAdObject **)obj2; - - if (object1->_posY < object2->_posY) return -1; - else if (object1->_posY > object2->_posY) return 1; - else return 0; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::displayRegionContentOld(CAdRegion *region) { - CAdGame *adGame = (CAdGame *)_gameRef; - CAdObject *obj; - - // display all objects in region sorted by _posY - do { - obj = NULL; - int minY = INT_MAX; - - // global objects - for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_active && _objects[i]->_editorOnly) { - _objects[i]->display(); - _objects[i]->_drawn = true; - } - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::update() { - return traverseNodes(true); -} - -////////////////////////////////////////////////////////////////////////// -void CAdScene::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 CAdScene::scrollToObject(CBObject *object) { - if (object) scrollTo(object->_posX, object->_posY - object->getHeight() / 2); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdScene::skipToObject(CBObject *object) { - if (object) skipTo(object->_posX, object->_posY - object->getHeight() / 2); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdScene::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 CAdScene::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // LoadActor - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "LoadActor") == 0) { - stack->correctParams(1); - CAdActor *act = new CAdActor(_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); - CAdEntity *ent = new CAdEntity(_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); - CScValue *val = stack->pop(); - - CAdEntity *ent = new CAdEntity(_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); - CScValue *val = stack->pop(); - CAdObject *obj = (CAdObject *)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); - CScValue *val1 = stack->pop(); - CScValue *val2 = stack->pop(); - if (val1->isNative()) { - skipToObject((CBObject *)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); - CScValue *val1 = stack->pop(); - CScValue *val2 = stack->pop(); - if (val1->isNative()) { - scrollToObject((CBObject *)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); - CScValue *val = stack->pop(); - if (val->isInt()) { - int layer = val->getInt(); - if (layer < 0 || layer >= _layers.getSize()) stack->pushNULL(); - else stack->pushNative(_layers[layer], true); - } else { - const char *LayerName = val->getString(); - bool LayerFound = false; - for (int i = 0; i < _layers.getSize(); i++) { - if (scumm_stricmp(LayerName, _layers[i]->_name) == 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 >= _waypointGroups.getSize()) 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(); - - CBObject *node = getNodeByName(nodeName); - if (node) stack->pushNative((CBScriptable *)node, true); - else stack->pushNULL(); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetFreeNode - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetFreeNode") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - - CAdObject *ret = NULL; - if (val->isInt()) { - int index = val->getInt(); - if (index >= 0 && index < _objects.getSize()) ret = _objects[index]; - } else { - const char *nodeName = val->getString(); - for (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i] && _objects[i]->_name && scumm_stricmp(_objects[i]->_name, 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(); - CScValue *val = stack->pop(); - - bool includeDecors = false; - if (!val->isNULL()) includeDecors = val->getBool(); - - if (_mainLayer) { - for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) { - CAdSceneNode *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 CBViewport(_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); - CScValue *val = stack->pop(); - - CAdLayer *layer = new CAdLayer(_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(); - CScValue *val = stack->pop(); - - CAdLayer *layer = new CAdLayer(_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 <= _layers.getSize() - 1) _layers.insertAt(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); - CScValue *val = stack->pop(); - - CAdLayer *toDelete = NULL; - if (val->isNative()) { - CBScriptable *temp = val->getNative(); - for (int i = 0; i < _layers.getSize(); i++) { - if (_layers[i] == temp) { - toDelete = _layers[i]; - break; - } - } - } else { - int index = val->getInt(); - if (index >= 0 && index < _layers.getSize()) { - 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 (int i = 0; i < _layers.getSize(); i++) { - if (_layers[i] == toDelete) { - _layers.removeAt(i); - _gameRef->unregisterObject(toDelete); - break; - } - } - stack->pushBool(true); - return STATUS_OK; - } - - else return CBObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdScene::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.getSize()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumWaypointGroups (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumWaypointGroups") == 0) { - _scValue->setInt(_waypointGroups.getSize()); - 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.getSize()); - 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 CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdScene::scToString() { - return "[scene object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::addObject(CAdObject *object) { - _objects.add(object); - return _gameRef->registerObject(object); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::removeObject(CAdObject *object) { - for (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i] == object) { - _objects.removeAt(i); - return _gameRef->unregisterObject(object); - } - } - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::saveAsText(CBDynBuffer *buffer, int indent) { - int i; - - buffer->putTextIndent(indent, "SCENE {\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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 (i = 0; i < _scripts.getSize(); 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"); - - CBBase::saveAsText(buffer, indent + 2); - - // waypoints - buffer->putTextIndent(indent + 2, "; ----- waypoints\n"); - for (i = 0; i < _waypointGroups.getSize(); i++) _waypointGroups[i]->saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent + 2, "\n"); - - // layers - buffer->putTextIndent(indent + 2, "; ----- layers\n"); - for (i = 0; i < _layers.getSize(); i++) _layers[i]->saveAsText(buffer, indent + 2); - - // scale levels - buffer->putTextIndent(indent + 2, "; ----- scale levels\n"); - for (i = 0; i < _scaleLevels.getSize(); i++) _scaleLevels[i]->saveAsText(buffer, indent + 2); - - // rotation levels - buffer->putTextIndent(indent + 2, "; ----- rotation levels\n"); - for (i = 0; i < _rotLevels.getSize(); i++) _rotLevels[i]->saveAsText(buffer, indent + 2); - - - buffer->putTextIndent(indent + 2, "\n"); - - // free entities - buffer->putTextIndent(indent + 2, "; ----- free entities\n"); - for (i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY) { - _objects[i]->saveAsText(buffer, indent + 2); - - } - } - - - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::sortScaleLevels() { - bool changed; - do { - changed = false; - for (int i = 0; i < _scaleLevels.getSize() - 1; i++) { - if (_scaleLevels[i]->_posY > _scaleLevels[i + 1]->_posY) { - CAdScaleLevel *sl = _scaleLevels[i]; - _scaleLevels[i] = _scaleLevels[i + 1]; - _scaleLevels[i + 1] = sl; - - changed = true; - } - } - - } while (changed); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::sortRotLevels() { - bool changed; - do { - changed = false; - for (int i = 0; i < _rotLevels.getSize() - 1; i++) { - if (_rotLevels[i]->_posX > _rotLevels[i + 1]->_posX) { - CAdRotLevel *rl = _rotLevels[i]; - _rotLevels[i] = _rotLevels[i + 1]; - _rotLevels[i + 1] = rl; - - changed = true; - } - } - - } while (changed); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -float CAdScene::getScaleAt(int Y) { - CAdScaleLevel *prev = NULL; - CAdScaleLevel *next = NULL; - - for (int i = 0; i < _scaleLevels.getSize(); i++) { - /* CAdScaleLevel *xxx = _scaleLevels[i];*/ - /* int j = _scaleLevels.getSize(); */ - 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 CAdScene::persist(CBPersistMgr *persistMgr) { - CBObject::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 CAdScene::afterLoad() { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, CBObject *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) { - /* - if (X1 > X2) - { - Swap(&X1, &X2); - Swap(&Y1, &Y2); - } - */ - - 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 { - /* - if (Y1 > Y2) { - Swap(&X1, &X2); - Swap(&Y1, &Y2); - } - */ - - 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 CAdScene::correctTargetPoint(int startX, int startY, int *argX, int *argY, bool checkFreeObjects, CBObject *requester) { - int x = *argX; - int y = *argY; - - if (isWalkableAt(x, y, checkFreeObjects, requester) || !_mainLayer) { - return STATUS_OK; - } - - // right - int length_right = 0; - bool found_right = false; - for (x = *argX, y = *argY; x < _mainLayer->_width; x++, length_right++) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x - 5, y, checkFreeObjects, requester)) { - found_right = true; - break; - } - } - - // left - int length_left = 0; - bool found_left = false; - for (x = *argX, y = *argY; x >= 0; x--, length_left--) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x + 5, y, checkFreeObjects, requester)) { - found_left = true; - break; - } - } - - // up - int length_up = 0; - bool found_up = false; - for (x = *argX, y = *argY; y >= 0; y--, length_up--) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y + 5, checkFreeObjects, requester)) { - found_up = true; - break; - } - } - - // down - int length_down = 0; - bool found_down = false; - for (x = *argX, y = *argY; y < _mainLayer->_height; y++, length_down++) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y - 5, checkFreeObjects, requester)) { - found_down = true; - break; - } - } - - if (!found_left && !found_right && !found_up && !found_down) { - return STATUS_OK; - } - - int OffsetX = INT_MAX, OffsetY = INT_MAX; - - if (found_left && found_right) { - if (abs(length_left) < abs(length_right)) OffsetX = length_left; - else OffsetX = length_right; - } else if (found_left) OffsetX = length_left; - else if (found_right) OffsetX = length_right; - - if (found_up && found_down) { - if (abs(length_up) < abs(length_down)) OffsetY = length_up; - else OffsetY = length_down; - } else if (found_up) OffsetY = length_up; - else if (found_down) OffsetY = length_down; - - 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 CAdScene::pfPointsStart() { - _pfPointsNum = 0; -} - - -////////////////////////////////////////////////////////////////////////// -void CAdScene::pfPointsAdd(int x, int y, int distance) { - if (_pfPointsNum >= _pfPath.getSize()) { - _pfPath.add(new CAdPathPoint(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 CAdScene::getViewportOffset(int *offsetX, int *offsetY) { - CAdGame *adGame = (CAdGame *)_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 CAdScene::getViewportSize(int *width, int *height) { - CAdGame *adGame = (CAdGame *)_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 CAdScene::getOffsetLeft() { - int viewportX; - getViewportOffset(&viewportX); - - return _offsetLeft - viewportX; -} - - -////////////////////////////////////////////////////////////////////////// -int CAdScene::getOffsetTop() { - int viewportY; - getViewportOffset(NULL, &viewportY); - - return _offsetTop - viewportY; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::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 CAdScene::setOffset(int offsetLeft, int offsetTop) { - _offsetLeft = offsetLeft; - _offsetTop = offsetTop; -} - - -////////////////////////////////////////////////////////////////////////// -CBObject *CAdScene::getNodeByName(const char *name) { - CBObject *ret = NULL; - - // dependent objects - for (int i = 0; i < _layers.getSize(); i++) { - CAdLayer *layer = _layers[i]; - for (int j = 0; j < layer->_nodes.getSize(); j++) { - CAdSceneNode *node = layer->_nodes[j]; - if ((node->_type == OBJECT_ENTITY && !scumm_stricmp(name, node->_entity->_name)) || - (node->_type == OBJECT_REGION && !scumm_stricmp(name, node->_region->_name))) { - 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 (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY && !scumm_stricmp(name, _objects[i]->_name)) { - return _objects[i]; - } - } - - // waypoint groups - for (int i = 0; i < _waypointGroups.getSize(); i++) { - if (!scumm_stricmp(name, _waypointGroups[i]->_name)) { - return _waypointGroups[i]; - } - } - - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::saveState() { - return persistState(true); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::loadState() { - return persistState(false); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::persistState(bool saving) { - if (!_persistentState) return STATUS_OK; - - CAdGame *adGame = (CAdGame *)_gameRef; - CAdSceneState *state = adGame->getSceneState(_filename, saving); - if (!state) return STATUS_OK; - - CAdNodeState *nodeState; - - // dependent objects - for (int i = 0; i < _layers.getSize(); i++) { - CAdLayer *layer = _layers[i]; - for (int j = 0; j < layer->_nodes.getSize(); j++) { - CAdSceneNode *node = layer->_nodes[j]; - switch (node->_type) { - case OBJECT_ENTITY: - if (!node->_entity->_saveState) continue; - nodeState = state->getNodeState(node->_entity->_name, 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->_name, saving); - if (nodeState) { - if (saving) nodeState->_active = node->_region->_active; - else node->_region->_active = nodeState->_active; - } - break; - default: - warning("CAdScene::PersistState - unhandled enum"); - break; - } - } - } - - // free entities - for (int i = 0; i < _objects.getSize(); i++) { - if (!_objects[i]->_saveState) continue; - if (_objects[i]->_type == OBJECT_ENTITY) { - nodeState = state->getNodeState(_objects[i]->_name, saving); - if (nodeState) { - nodeState->transferEntity((CAdEntity *)_objects[i], _persistentStateSprites, saving); - //if(Saving) NodeState->_active = _objects[i]->_active; - //else _objects[i]->_active = NodeState->_active; - } - } - } - - // waypoint groups - for (int i = 0; i < _waypointGroups.getSize(); i++) { - nodeState = state->getNodeState(_waypointGroups[i]->_name, saving); - if (nodeState) { - if (saving) nodeState->_active = _waypointGroups[i]->_active; - else _waypointGroups[i]->_active = nodeState->_active; - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -float CAdScene::getRotationAt(int x, int y) { - CAdRotLevel *prev = NULL; - CAdRotLevel *next = NULL; - - for (int i = 0; i < _rotLevels.getSize(); i++) { - /* CAdRotLevel *xxx = _rotLevels[i]; - int j = _rotLevels.getSize();*/ - 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 CAdScene::handleItemAssociations(const char *itemName, bool show) { - for (int i = 0; i < _layers.getSize(); i++) { - CAdLayer *layer = _layers[i]; - for (int j = 0; j < layer->_nodes.getSize(); j++) { - if (layer->_nodes[j]->_type == OBJECT_ENTITY) { - CAdEntity *ent = layer->_nodes[j]->_entity; - - if (ent->_item && strcmp(ent->_item, itemName) == 0) ent->_active = show; - } - } - } - - for (int i = 0; i < _objects.getSize(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY) { - CAdEntity *ent = (CAdEntity *)_objects[i]; - if (ent->_item && strcmp(ent->_item, itemName) == 0) ent->_active = show; - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::getRegionsAt(int x, int y, CAdRegion **regionList, int numRegions) { - int numUsed = 0; - if (_mainLayer) { - for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) { - CAdSceneNode *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 CAdScene::restoreDeviceObjects() { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CBObject *CAdScene::getNextAccessObject(CBObject *currObject) { - CBArray objects; - getSceneObjects(objects, true); - - if (objects.getSize() == 0) return NULL; - else { - if (currObject != NULL) { - for (int i = 0; i < objects.getSize(); i++) { - if (objects[i] == currObject) { - if (i < objects.getSize() - 1) return objects[i + 1]; - else break; - } - } - } - return objects[0]; - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -CBObject *CAdScene::getPrevAccessObject(CBObject *currObject) { - CBArray objects; - getSceneObjects(objects, true); - - if (objects.getSize() == 0) return NULL; - else { - if (currObject != NULL) { - for (int i = objects.getSize() - 1; i >= 0; i--) { - if (objects[i] == currObject) { - if (i > 0) return objects[i - 1]; - else break; - } - } - } - return objects[objects.getSize() - 1]; - } - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::getSceneObjects(CBArray &objects, bool interactiveOnly) { - for (int i = 0; i < _layers.getSize(); i++) { - // close-up layer -> remove everything below it - if (interactiveOnly && _layers[i]->_closeUp) objects.removeAll(); - - - for (int j = 0; j < _layers[i]->_nodes.getSize(); j++) { - CAdSceneNode *node = _layers[i]->_nodes[j]; - switch (node->_type) { - case OBJECT_ENTITY: { - CAdEntity *ent = node->_entity; - if (ent->_active && (ent->_registrable || !interactiveOnly)) - objects.add(ent); - } - break; - - case OBJECT_REGION: { - CBArray regionObj; - getRegionObjects(node->_region, regionObj, interactiveOnly); - for (int newIndex = 0; newIndex < regionObj.getSize(); newIndex++) { - bool found = false; - for (int old = 0; old < objects.getSize(); old++) { - if (objects[old] == regionObj[newIndex]) { - found = true; - break; - } - } - if (!found) objects.add(regionObj[newIndex]); - } - //if(RegionObj.getSize() > 0) Objects.Append(RegionObj); - } - break; - default: - warning("CAdScene::GetSceneObjects - Unhandled enum"); - break; - } - } - } - - // objects outside any region - CBArray regionObj; - getRegionObjects(NULL, regionObj, interactiveOnly); - for (int newIndex = 0; newIndex < regionObj.getSize(); newIndex++) { - bool found = false; - for (int old = 0; old < objects.getSize(); old++) { - if (objects[old] == regionObj[newIndex]) { - found = true; - break; - } - } - if (!found) objects.add(regionObj[newIndex]); - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdScene::getRegionObjects(CAdRegion *region, CBArray &objects, bool interactiveOnly) { - CAdGame *adGame = (CAdGame *)_gameRef; - CAdObject *obj; - - // global objects - for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 - qsort(objects.getData(), objects.getSize(), sizeof(CAdObject *), CAdScene::compareObjs); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdScene.h b/engines/wintermute/ad/AdScene.h deleted file mode 100644 index f77c64aa9b..0000000000 --- a/engines/wintermute/ad/AdScene.h +++ /dev/null @@ -1,181 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BFader.h" - -namespace WinterMute { - -class CUIWindow; -class CAdObject; -class CAdRegion; -class CBViewport; -class CAdLayer; -class CBPoint; -class CAdWaypointGroup; -class CAdPath; -class CAdScaleLevel; -class CAdRotLevel; -class CAdPathPoint; -class CAdScene : public CBObject { -public: - - CBObject *getNextAccessObject(CBObject *CurrObject); - CBObject *getPrevAccessObject(CBObject *CurrObject); - bool getSceneObjects(CBArray &Objects, bool InteractiveOnly); - bool getRegionObjects(CAdRegion *Region, CBArray &Objects, bool InteractiveOnly); - - bool afterLoad(); - - bool getRegionsAt(int X, int Y, CAdRegion **RegionList, int NumRegions); - bool handleItemAssociations(const char *ItemName, bool Show); - CUIWindow *_shieldWindow; - float getRotationAt(int X, int Y); - bool loadState(); - bool saveState(); - bool _persistentState; - bool _persistentStateSprites; - CBObject *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); - CBViewport *_viewport; - CBFader *_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, CBObject *Requester = NULL); - bool correctTargetPoint2(int StartX, int StartY, int *TargetX, int *TargetY, bool CheckFreeObjects, CBObject *Requester); - DECLARE_PERSISTENT(CAdScene, CBObject) - bool displayRegionContent(CAdRegion *Region = NULL, bool Display3DOnly = false); - bool displayRegionContentOld(CAdRegion *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(CBDynBuffer *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(CBObject *Object); - void scrollToObject(CBObject *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, CBObject *Requester = NULL); - bool isWalkableAt(int X, int Y, bool CheckFreeObjects = false, CBObject *Requester = NULL); - CAdLayer *_mainLayer; - float getZoomAt(int X, int Y); - bool getPath(CBPoint source, CBPoint target, CAdPath *path, CBObject *requester = NULL); - CAdScene(CBGame *inGame); - virtual ~CAdScene(); - CBArray _layers; - CBArray _objects; - CBArray _waypointGroups; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - int _width; - int _height; - bool addObject(CAdObject *Object); - bool removeObject(CAdObject *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; - CBArray _scaleLevels; - CBArray _rotLevels; - - virtual bool restoreDeviceObjects(); - int getPointsDist(CBPoint p1, CBPoint p2, CBObject *requester = NULL); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - - -private: - bool persistState(bool Saving = true); - void pfAddWaypointGroup(CAdWaypointGroup *Wpt, CBObject *Requester = NULL); - bool _pfReady; - CBPoint *_pfTarget; - CAdPath *_pfTargetPath; - CBObject *_pfRequester; - CBArray _pfPath; - - int _offsetTop; - int _offsetLeft; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdSceneNode.cpp b/engines/wintermute/ad/AdSceneNode.cpp deleted file mode 100644 index 5f518e5442..0000000000 --- a/engines/wintermute/ad/AdSceneNode.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdSceneNode.h" -#include "engines/wintermute/base/BGame.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdSceneNode, false) - -////////////////////////////////////////////////////////////////////////// -CAdSceneNode::CAdSceneNode(CBGame *inGame): CBObject(inGame) { - _type = OBJECT_NONE; - _region = NULL; - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdSceneNode::~CAdSceneNode() { - _gameRef->unregisterObject(_region); - _region = NULL; - - _gameRef->unregisterObject(_entity); - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSceneNode::setEntity(CAdEntity *entity) { - _type = OBJECT_ENTITY; - _entity = entity; - return _gameRef->registerObject(entity); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSceneNode::setRegion(CAdRegion *region) { - _type = OBJECT_REGION; - _region = region; - return _gameRef->registerObject(region); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSceneNode::persist(CBPersistMgr *persistMgr) { - - CBObject::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/AdSceneNode.h b/engines/wintermute/ad/AdSceneNode.h deleted file mode 100644 index d081959934..0000000000 --- a/engines/wintermute/ad/AdSceneNode.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/AdTypes.h" // Added by ClassView -#include "engines/wintermute/ad/AdRegion.h" // Added by ClassView -#include "engines/wintermute/ad/AdEntity.h" - -namespace WinterMute { - -class CAdSceneNode : public CBObject { -public: - DECLARE_PERSISTENT(CAdSceneNode, CBObject) - bool setRegion(CAdRegion *region); - bool setEntity(CAdEntity *entity); - CAdEntity *_entity; - CAdRegion *_region; - TObjectType _type; - CAdSceneNode(CBGame *inGame); - virtual ~CAdSceneNode(); - -}; - -} - -#endif diff --git a/engines/wintermute/ad/AdSceneState.cpp b/engines/wintermute/ad/AdSceneState.cpp deleted file mode 100644 index 5dfb8c537e..0000000000 --- a/engines/wintermute/ad/AdSceneState.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/persistent.h" -#include "engines/wintermute/ad/AdSceneState.h" -#include "engines/wintermute/ad/AdNodeState.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdSceneState, false) - -////////////////////////////////////////////////////////////////////////// -CAdSceneState::CAdSceneState(CBGame *inGame): CBBase(inGame) { - _filename = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdSceneState::~CAdSceneState() { - delete[] _filename; - _filename = NULL; - - for (int i = 0; i < _nodeStates.getSize(); i++) delete _nodeStates[i]; - _nodeStates.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSceneState::persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_filename)); - _nodeStates.persist(persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CAdSceneState::setFilename(const char *filename) { - delete[] _filename; - _filename = new char [strlen(filename) + 1]; - if (_filename) strcpy(_filename, filename); -} - - -////////////////////////////////////////////////////////////////////////// -CAdNodeState *CAdSceneState::getNodeState(char *name, bool saving) { - for (int i = 0; i < _nodeStates.getSize(); i++) { - if (scumm_stricmp(_nodeStates[i]->_name, name) == 0) return _nodeStates[i]; - } - - if (saving) { - CAdNodeState *ret = new CAdNodeState(_gameRef); - ret->setName(name); - _nodeStates.add(ret); - - return ret; - } else return NULL; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdSceneState.h b/engines/wintermute/ad/AdSceneState.h deleted file mode 100644 index 82207f383c..0000000000 --- a/engines/wintermute/ad/AdSceneState.h +++ /dev/null @@ -1,51 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" -#include "engines/wintermute/coll_templ.h" - -namespace WinterMute { -class CAdNodeState; -class CAdSceneState : public CBBase { -public: - CAdNodeState *getNodeState(char *name, bool saving); - void setFilename(const char *filename); - DECLARE_PERSISTENT(CAdSceneState, CBBase) - CAdSceneState(CBGame *inGame); - virtual ~CAdSceneState(); - char *_filename; - CBArray _nodeStates; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdSentence.cpp b/engines/wintermute/ad/AdSentence.cpp deleted file mode 100644 index 98926caac6..0000000000 --- a/engines/wintermute/ad/AdSentence.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdSentence.h" -#include "engines/wintermute/ad/AdTalkDef.h" -#include "engines/wintermute/ad/AdTalkNode.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/ad/AdScene.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdSentence, false) - -////////////////////////////////////////////////////////////////////////// -CAdSentence::CAdSentence(CBGame *inGame): CBBase(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; -} - - -////////////////////////////////////////////////////////////////////////// -CAdSentence::~CAdSentence() { - 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 CAdSentence::setText(const char *text) { - if (_text) delete [] _text; - _text = new char[strlen(text) + 1]; - if (_text) strcpy(_text, text); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdSentence::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 *CAdSentence::getCurrentStance() { - return getStance(_currentStance); -} - - -////////////////////////////////////////////////////////////////////////// -char *CAdSentence::getNextStance() { - _currentStance++; - return getStance(_currentStance); -} - - -////////////////////////////////////////////////////////////////////////// -char *CAdSentence::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) { - _tempStance[curr - start] = '\0'; - strncpy(_tempStance, start, curr - start); - } - - return _tempStance; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSentence::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 - ((CAdGame *)_gameRef)->_scene->getOffsetLeft(); - y = y - ((CAdGame *)_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 CAdSentence::setSound(CBSound *sound) { - if (!sound) return; - delete _sound; - _sound = sound; - _soundStarted = false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSentence::finish() { - if (_sound) _sound->stop(); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSentence::persist(CBPersistMgr *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 CAdSentence::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"); - - Common::SeekableReadStream *file = _gameRef->_fileManager->openFile(talkDefFileName.c_str()); - if (file) { - _gameRef->_fileManager->closeFile(file); - } else return STATUS_OK; // no talk def file found - - - _talkDef = new CAdTalkDef(_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 CAdSentence::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 (int i = 0; i < _talkDef->_nodes.getSize(); i++) { - if (_talkDef->_nodes[i]->isInTimeInterval(currentTime, dir)) { - talkNodeFound = true; - - CBSprite *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) { - CBSprite *newSprite = _talkDef->getDefaultSprite(dir); - if (newSprite) { - if (newSprite != _currentSprite) newSprite->reset(); - _currentSprite = newSprite; - } else _currentSprite = NULL; - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdSentence::CanSkip() { - // prevent accidental sentence skipping (TODO make configurable) - return (_gameRef->_timer - _startTime) > 300; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdSentence.h b/engines/wintermute/ad/AdSentence.h deleted file mode 100644 index 954568878e..0000000000 --- a/engines/wintermute/ad/AdSentence.h +++ /dev/null @@ -1,85 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.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 CAdTalkDef; -class CBFont; -class CBSprite; -class CBSound; -class CAdSentence : public CBBase { -public: - bool _freezable; - bool _fixedPos; - CBSprite *_currentSprite; - char *_currentSkelAnim; - bool update(TDirection dir = DI_DOWN); - bool setupTalkFile(const char *soundFilename); - DECLARE_PERSISTENT(CAdSentence, CBBase) - bool finish(); - void setSound(CBSound *Sound); - bool _soundStarted; - CBSound *_sound; - TTextAlign _align; - bool display(); - int _width; - Point32 _pos; - CBFont *_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; - CAdSentence(CBGame *inGame); - virtual ~CAdSentence(); - CAdTalkDef *_talkDef; - - bool CanSkip(); - -private: - char *_tempStance; - char *getStance(int stance); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdSpriteSet.cpp b/engines/wintermute/ad/AdSpriteSet.cpp deleted file mode 100644 index 127d42d02b..0000000000 --- a/engines/wintermute/ad/AdSpriteSet.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdSpriteSet.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdSpriteSet, false) - -////////////////////////////////////////////////////////////////////////// -CAdSpriteSet::CAdSpriteSet(CBGame *inGame, CBObject *owner): CBObject(inGame) { - _owner = owner; - - for (int i = 0; i < NUM_DIRECTIONS; i++) - _sprites[i] = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdSpriteSet::~CAdSpriteSet() { - for (int i = 0; i < NUM_DIRECTIONS; i++) { - delete _sprites[i]; - _sprites[i] = NULL; - } - - _owner = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdSpriteSet::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdSpriteSet::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 CAdSpriteSet::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; - CBParser parser(_gameRef); - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SPRITESET) { - _gameRef->LOG(0, "'SPRITESET' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - CBSprite *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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CAdSpriteSet::persist(CBPersistMgr *persistMgr) { - - CBObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_owner)); - for (int i = 0; i < NUM_DIRECTIONS; i++) { - persistMgr->transfer("", &_sprites[i]); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CBSprite *CAdSpriteSet::getSprite(TDirection direction) { - int dir = (int)direction; - if (dir < 0) dir = 0; - if (dir >= NUM_DIRECTIONS) dir = NUM_DIRECTIONS - 1; - - CBSprite *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 CAdSpriteSet::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "SPRITESET {\n"); - if (_name) buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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]->_filename); - break; - case DI_UPRIGHT: - buffer->putTextIndent(indent + 2, "UP_RIGHT=\"%s\"\n", _sprites[i]->_filename); - break; - case DI_RIGHT: - buffer->putTextIndent(indent + 2, "RIGHT=\"%s\"\n", _sprites[i]->_filename); - break; - case DI_DOWNRIGHT: - buffer->putTextIndent(indent + 2, "DOWN_RIGHT=\"%s\"\n", _sprites[i]->_filename); - break; - case DI_DOWN: - buffer->putTextIndent(indent + 2, "DOWN=\"%s\"\n", _sprites[i]->_filename); - break; - case DI_DOWNLEFT: - buffer->putTextIndent(indent + 2, "DOWN_LEFT=\"%s\"\n", _sprites[i]->_filename); - break; - case DI_LEFT: - buffer->putTextIndent(indent + 2, "LEFT=\"%s\"\n", _sprites[i]->_filename); - break; - case DI_UPLEFT: - buffer->putTextIndent(indent + 2, "UP_LEFT=\"%s\"\n", _sprites[i]->_filename); - break; - } - } - } - - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CAdSpriteSet::containsSprite(CBSprite *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/AdSpriteSet.h b/engines/wintermute/ad/AdSpriteSet.h deleted file mode 100644 index ba5c6fb75b..0000000000 --- a/engines/wintermute/ad/AdSpriteSet.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" -#include "engines/wintermute/base/BSprite.h" // Added by ClassView - -namespace WinterMute { - -class CAdSpriteSet : public CBObject { -public: - bool containsSprite(CBSprite *sprite); - virtual bool saveAsText(CBDynBuffer *buffer, int indent = 0); - CBSprite *getSprite(TDirection direction); - DECLARE_PERSISTENT(CAdSpriteSet, CBObject) - CBObject *_owner; - CAdSpriteSet(CBGame *inGame, CBObject *owner = NULL); - virtual ~CAdSpriteSet(); - 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); - CBSprite *_sprites[NUM_DIRECTIONS]; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdTalkDef.cpp b/engines/wintermute/ad/AdTalkDef.cpp deleted file mode 100644 index b598226413..0000000000 --- a/engines/wintermute/ad/AdTalkDef.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdTalkDef.h" -#include "engines/wintermute/ad/AdTalkNode.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/ad/AdSpriteSet.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/utils/utils.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdTalkDef, false) - -////////////////////////////////////////////////////////////////////////// -CAdTalkDef::CAdTalkDef(CBGame *inGame): CBObject(inGame) { - _defaultSpriteFilename = NULL; - _defaultSprite = NULL; - - _defaultSpriteSetFilename = NULL; - _defaultSpriteSet = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdTalkDef::~CAdTalkDef() { - for (int i = 0; i < _nodes.getSize(); i++) delete _nodes[i]; - _nodes.removeAll(); - - delete[] _defaultSpriteFilename; - delete _defaultSprite; - _defaultSpriteFilename = NULL; - _defaultSprite = NULL; - - delete[] _defaultSpriteSetFilename; - delete _defaultSpriteSet; - _defaultSpriteSetFilename = NULL; - _defaultSpriteSet = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkDef::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdTalkDef::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - CBUtils::setString(&_filename, 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 CAdTalkDef::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; - CBParser parser(_gameRef); - - 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: { - CAdTalkNode *Node = new CAdTalkNode(_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: - CBUtils::setString(&_defaultSpriteFilename, (char *)params); - break; - - case TOKEN_DEFAULT_SPRITESET_FILE: - CBUtils::setString(&_defaultSpriteSetFilename, (char *)params); - break; - - case TOKEN_DEFAULT_SPRITESET: { - delete _defaultSpriteSet; - _defaultSpriteSet = new CAdSpriteSet(_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 CBSprite(_gameRef); - if (!_defaultSprite || DID_FAIL(_defaultSprite->loadFile(_defaultSpriteFilename))) return STATUS_FAILED; - } - - if (_defaultSpriteSetFilename) { - _defaultSpriteSet = new CAdSpriteSet(_gameRef); - if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) return STATUS_FAILED; - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkDef::persist(CBPersistMgr *persistMgr) { - - CBObject::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 CAdTalkDef::saveAsText(CBDynBuffer *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 (int i = 0; i < _nodes.getSize(); i++) { - _nodes[i]->saveAsText(buffer, indent + 2); - buffer->putTextIndent(indent, "\n"); - } - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkDef::loadDefaultSprite() { - if (_defaultSpriteFilename && !_defaultSprite) { - _defaultSprite = new CBSprite(_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 CAdSpriteSet(_gameRef); - if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) { - delete _defaultSpriteSet; - _defaultSpriteSet = NULL; - return STATUS_FAILED; - } else return STATUS_OK; - } else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CBSprite *CAdTalkDef::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/AdTalkDef.h b/engines/wintermute/ad/AdTalkDef.h deleted file mode 100644 index 81d6475013..0000000000 --- a/engines/wintermute/ad/AdTalkDef.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" - -namespace WinterMute { -class CAdTalkNode; -class CAdSpriteSet; -class CAdTalkDef : public CBObject { -public: - char *_defaultSpriteSetFilename; - CAdSpriteSet *_defaultSpriteSet; - CBSprite *getDefaultSprite(TDirection Dir); - bool loadDefaultSprite(); - DECLARE_PERSISTENT(CAdTalkDef, CBObject) - - CAdTalkDef(CBGame *inGame); - virtual ~CAdTalkDef(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - CBArray _nodes; - char *_defaultSpriteFilename; - CBSprite *_defaultSprite; - virtual bool saveAsText(CBDynBuffer *buffer, int indent = 0); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdTalkHolder.cpp b/engines/wintermute/ad/AdTalkHolder.cpp deleted file mode 100644 index e1a91792ce..0000000000 --- a/engines/wintermute/ad/AdTalkHolder.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdTalkHolder.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/wintermute.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdTalkHolder, false) - -////////////////////////////////////////////////////////////////////////// -CAdTalkHolder::CAdTalkHolder(CBGame *inGame): CAdObject(inGame) { - _sprite = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CAdTalkHolder::~CAdTalkHolder() { - delete _sprite; - _sprite = NULL; - - for (int i = 0; i < _talkSprites.getSize(); i++) - delete _talkSprites[i]; - _talkSprites.removeAll(); - - for (int i = 0; i < _talkSpritesEx.getSize(); i++) - delete _talkSpritesEx[i]; - _talkSpritesEx.removeAll(); -} - -////////////////////////////////////////////////////////////////////////// -CBSprite *CAdTalkHolder::getTalkStance(const char *stance) { - CBSprite *ret = NULL; - - - // forced stance? - if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { - _forcedTalkAnimUsed = true; - delete _animSprite; - _animSprite = new CBSprite(_gameRef, this); - if (_animSprite) { - bool res = _animSprite->loadFile(_forcedTalkAnimName); - if (DID_FAIL(res)) { - _gameRef->LOG(res, "CAdTalkHolder::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", _name, _forcedTalkAnimName); - delete _animSprite; - _animSprite = NULL; - } else return _animSprite; - } - } - - - if (stance != NULL) { - // search special talk stances - for (int i = 0; i < _talkSpritesEx.getSize(); i++) { - if (scumm_stricmp(_talkSpritesEx[i]->_name, stance) == 0) { - ret = _talkSpritesEx[i]; - break; - } - } - if (ret == NULL) { - // serach generic talk stances - for (int i = 0; i < _talkSprites.getSize(); i++) { - if (scumm_stricmp(_talkSprites[i]->_name, stance) == 0) { - ret = _talkSprites[i]; - break; - } - } - } - } - - // not a valid stance? get a random one - if (ret == NULL) { - if (_talkSprites.getSize() < 1) ret = _sprite; - else { - // TODO: remember last - int rnd = g_wintermute->randInt(0, _talkSprites.getSize() - 1); - ret = _talkSprites[rnd]; - } - } - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CAdTalkHolder::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetSprite - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetSprite") == 0) { - stack->correctParams(1); - - CScValue *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(); - CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_sprite->_filename); - 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(); - - CBSprite *spr = new CBSprite(_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 (int i = 0; i < _talkSpritesEx.getSize(); i++) { - if (scumm_stricmp(_talkSpritesEx[i]->_filename, filename) == 0) { - if (_currentSprite == _talkSpritesEx[i]) - setCurrent = true; - if (_tempSprite2 == _talkSpritesEx[i]) - setTemp2 = true; - delete _talkSpritesEx[i]; - _talkSpritesEx.removeAt(i); - break; - } - } - } else { - for (int i = 0; i < _talkSprites.getSize(); i++) { - if (scumm_stricmp(_talkSprites[i]->_filename, filename) == 0) { - if (_currentSprite == _talkSprites[i]) - setCurrent = true; - if (_tempSprite2 == _talkSprites[i]) - setTemp2 = true; - delete _talkSprites[i]; - _talkSprites.removeAt(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; - - CBSprite *spr = new CBSprite(_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 (int i = 0; i < _talkSpritesEx.getSize(); i++) { - if (_talkSpritesEx[i] == _currentSprite) - setCurrent = true; - if (_talkSpritesEx[i] == _tempSprite2) - setTemp2 = true; - delete _talkSpritesEx[i]; - } - _talkSpritesEx.removeAll(); - } else { - for (int i = 0; i < _talkSprites.getSize(); i++) { - if (_talkSprites[i] == _currentSprite) setCurrent = true; - if (_talkSprites[i] == _tempSprite2) setTemp2 = true; - delete _talkSprites[i]; - } - _talkSprites.removeAll(); - } - - // 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 CAdObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdTalkHolder::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type (RO) - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("talk-holder"); - return _scValue; - } - - else return CAdObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkHolder::scSetProperty(const char *name, CScValue *value) { - /* - ////////////////////////////////////////////////////////////////////////// - // Item - ////////////////////////////////////////////////////////////////////////// - if(strcmp(name, "Item")==0){ - SetItem(value->getString()); - return STATUS_OK; - } - - else*/ return CAdObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CAdTalkHolder::scToString() { - return "[talk-holder object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkHolder::saveAsText(CBDynBuffer *buffer, int indent) { - for (int i = 0; i < _talkSprites.getSize(); i++) { - if (_talkSprites[i]->_filename) - buffer->putTextIndent(indent + 2, "TALK=\"%s\"\n", _talkSprites[i]->_filename); - } - - for (int i = 0; i < _talkSpritesEx.getSize(); i++) { - if (_talkSpritesEx[i]->_filename) - buffer->putTextIndent(indent + 2, "TALK_SPECIAL=\"%s\"\n", _talkSpritesEx[i]->_filename); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkHolder::persist(CBPersistMgr *persistMgr) { - CAdObject::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/AdTalkHolder.h b/engines/wintermute/ad/AdTalkHolder.h deleted file mode 100644 index 9e6c3bbd63..0000000000 --- a/engines/wintermute/ad/AdTalkHolder.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/AdObject.h" - -namespace WinterMute { - -class CAdTalkHolder : public CAdObject { -public: - DECLARE_PERSISTENT(CAdTalkHolder, CAdObject) - virtual CBSprite *getTalkStance(const char *stance); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - CBSprite *_sprite; - CBArray _talkSprites; - CBArray _talkSpritesEx; - CAdTalkHolder(CBGame *inGame); - virtual ~CAdTalkHolder(); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdTalkNode.cpp b/engines/wintermute/ad/AdTalkNode.cpp deleted file mode 100644 index da2195be33..0000000000 --- a/engines/wintermute/ad/AdTalkNode.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdTalkNode.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/ad/AdSpriteSet.h" -#include "engines/wintermute/utils/utils.h" -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdTalkNode, false) - -////////////////////////////////////////////////////////////////////////// -CAdTalkNode::CAdTalkNode(CBGame *inGame): CBBase(inGame) { - _sprite = NULL; - _spriteFilename = NULL; - _spriteSet = NULL; - _spriteSetFilename = NULL; - _comment = NULL; - - _startTime = _endTime = 0; - _playToEnd = false; - _preCache = false; -} - - -////////////////////////////////////////////////////////////////////////// -CAdTalkNode::~CAdTalkNode() { - 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 CAdTalkNode::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; - CBParser parser(_gameRef); - - 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: - CBUtils::setString(&_spriteFilename, (char *)params); - break; - - case TOKEN_SPRITESET_FILE: - CBUtils::setString(&_spriteSetFilename, (char *)params); - break; - - case TOKEN_SPRITESET: { - delete _spriteSet; - _spriteSet = new CAdSpriteSet(_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) CBUtils::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 CBSprite(_gameRef); - if (!_sprite || DID_FAIL(_sprite->loadFile(_spriteFilename))) - return STATUS_FAILED; - } - - if (_preCache && _spriteSetFilename) { - delete _spriteSet; - _spriteSet = new CAdSpriteSet(_gameRef); - if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) - return STATUS_FAILED; - } - - return STATUS_OK; -} - - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkNode::persist(CBPersistMgr *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 CAdTalkNode::saveAsText(CBDynBuffer *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"); - - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkNode::loadSprite() { - if (_spriteFilename && !_sprite) { - _sprite = new CBSprite(_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 CAdSpriteSet(_gameRef); - if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) { - delete _spriteSet; - _spriteSet = NULL; - return STATUS_FAILED; - } else return STATUS_OK; - } - - else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdTalkNode::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; -} - - -////////////////////////////////////////////////////////////////////////// -CBSprite *CAdTalkNode::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/AdTalkNode.h b/engines/wintermute/ad/AdTalkNode.h deleted file mode 100644 index 11bbb353c1..0000000000 --- a/engines/wintermute/ad/AdTalkNode.h +++ /dev/null @@ -1,63 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" - -namespace WinterMute { -class CAdSpriteSet; -class CBSprite; -class CAdTalkNode : public CBBase { -public: - char *_spriteSetFilename; - CAdSpriteSet *_spriteSet; - CBSprite *getSprite(TDirection dir); - bool isInTimeInterval(uint32 time, TDirection dir); - bool loadSprite(); - DECLARE_PERSISTENT(CAdTalkNode, CBBase) - - CAdTalkNode(CBGame *inGame); - virtual ~CAdTalkNode(); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent = 0); - char *_spriteFilename; - CBSprite *_sprite; - uint32 _startTime; - uint32 _endTime; - bool _playToEnd; - bool _preCache; - char *_comment; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/AdTypes.h b/engines/wintermute/ad/AdTypes.h deleted file mode 100644 index b88d6fe259..0000000000 --- a/engines/wintermute/ad/AdTypes.h +++ /dev/null @@ -1,107 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 // WINTERMUTE_ADTYPES_H diff --git a/engines/wintermute/ad/AdWaypointGroup.cpp b/engines/wintermute/ad/AdWaypointGroup.cpp deleted file mode 100644 index 3080b34c09..0000000000 --- a/engines/wintermute/ad/AdWaypointGroup.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/AdWaypointGroup.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/base/BFileManager.h" -#include - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CAdWaypointGroup, false) - -////////////////////////////////////////////////////////////////////////// -CAdWaypointGroup::CAdWaypointGroup(CBGame *inGame): CBObject(inGame) { - _active = true; - _editorSelectedPoint = -1; - _lastMimicScale = -1; - _lastMimicX = _lastMimicY = INT_MIN; -} - - -////////////////////////////////////////////////////////////////////////// -CAdWaypointGroup::~CAdWaypointGroup() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void CAdWaypointGroup::cleanup() { - for (int i = 0; i < _points.getSize(); i++) - delete _points[i]; - _points.removeAll(); - _editorSelectedPoint = -1; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdWaypointGroup::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CAdWaypointGroup::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CAdWaypointGroup::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; - CBParser parser(_gameRef); - - 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 CBPoint(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 CAdWaypointGroup::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "WAYPOINTS {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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); - CBBase::saveAsText(buffer, indent + 2); - - for (int i = 0; i < _points.getSize(); i++) { - buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); - } - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdWaypointGroup::persist(CBPersistMgr *persistMgr) { - - CBObject::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; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CAdWaypointGroup::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 CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdWaypointGroup::scSetProperty(const char *name, CScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Active") == 0) { - _active = value->getBool(); - return STATUS_OK; - } - - else return CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -bool CAdWaypointGroup::mimic(CAdWaypointGroup *wpt, float scale, int argX, int argY) { - if (scale == _lastMimicScale && argX == _lastMimicX && argY == _lastMimicY) return STATUS_OK; - - cleanup(); - - for (int i = 0; i < wpt->_points.getSize(); 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 CBPoint(x + argX, y + argY)); - } - - _lastMimicScale = scale; - _lastMimicX = argX; - _lastMimicY = argY; - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ad/AdWaypointGroup.h b/engines/wintermute/ad/AdWaypointGroup.h deleted file mode 100644 index f7c9e4c361..0000000000 --- a/engines/wintermute/ad/AdWaypointGroup.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" - -namespace WinterMute { -class CBPoint; -class CAdWaypointGroup : public CBObject { -public: - float _lastMimicScale; - int _lastMimicX; - int _lastMimicY; - void cleanup(); - bool mimic(CAdWaypointGroup *wpt, float scale = 100.0f, int x = 0, int y = 0); - DECLARE_PERSISTENT(CAdWaypointGroup, CBObject) - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - bool _active; - CAdWaypointGroup(CBGame *inGame); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual ~CAdWaypointGroup(); - CBArray _points; - int _editorSelectedPoint; - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp new file mode 100644 index 0000000000..36f1aa8286 --- /dev/null +++ b/engines/wintermute/ad/ad_actor.cpp @@ -0,0 +1,1316 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/dctypes.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base_object.h" +#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_object.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/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/wintermute.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdActor, false) + + +////////////////////////////////////////////////////////////////////////// +CAdActor::CAdActor(CBGame *inGame): CAdTalkHolder(inGame) { + _path = new CAdPath(_gameRef); + + _type = OBJECT_ACTOR; + _dir = DI_LEFT; + + _walkSprite = NULL; + _standSprite = NULL; + _turnLeftSprite = NULL; + _turnRightSprite = NULL; + + _targetPoint = new CBPoint; + _afterWalkDir = DI_NONE; + + _animSprite2 = NULL; + + setDefaultAnimNames(); +} + +////////////////////////////////////////////////////////////////////////// +bool CAdActor::setDefaultAnimNames() { + _talkAnimName = "talk"; + _idleAnimName = "idle"; + _walkAnimName = "walk"; + _turnLeftAnimName = "turnleft"; + _turnRightAnimName = "turnright"; + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +CAdActor::~CAdActor() { + 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 (int i = 0; i < _talkSprites.getSize(); i++) { + delete _talkSprites[i]; + } + _talkSprites.removeAll(); + + for (int i = 0; i < _talkSpritesEx.getSize(); i++) { + delete _talkSpritesEx[i]; + } + _talkSpritesEx.removeAll(); + + for (int i = 0; i < _anims.getSize(); i++) { + delete _anims[i]; + _anims[i] = NULL; + } + _anims.removeAll(); + +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdActor::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdActor::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdActor::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; + CBParser parser(_gameRef); + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ACTOR) { + _gameRef->LOG(0, "'ACTOR' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + CAdGame *adGame = (CAdGame *)_gameRef; + CAdSpriteSet *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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CAdSpriteSet(_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 CBSprite(_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; + CBRegion *rgn = new CBRegion(_gameRef); + CBRegion *crgn = new CBRegion(_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; + CAdWaypointGroup *wpt = new CAdWaypointGroup(_gameRef); + CAdWaypointGroup *cwpt = new CAdWaypointGroup(_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: { + CAdSpriteSet *Anim = new CAdSpriteSet(_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 CAdActor::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 CAdActor::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; + + ((CAdGame *)_gameRef)->_scene->correctTargetPoint(_posX, _posY, &_targetPoint->x, &_targetPoint->y, true, this); + + _state = STATE_SEARCHING_PATH; + +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdActor::display() { + if (_active) updateSounds(); + + uint32 alpha; + if (_alphaColor != 0) alpha = _alphaColor; + else alpha = _shadowable ? ((CAdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY, true) : 0xFFFFFFFF; + + float scaleX, scaleY; + getScale(&scaleX, &scaleY); + + + float rotate; + if (_rotatable) { + if (_rotateValid) rotate = _rotate; + else rotate = ((CAdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; + } else rotate = 0.0f; + + if (_active) displaySpriteAttachments(true); + + if (_currentSprite && _active) { + bool reg = _registrable; + if (_ignoreItems && ((CAdGame *)_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 CAdActor::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 { + CAdSpriteSet *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 { + CAdSpriteSet *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 { + CAdSpriteSet *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 (((CAdGame *)_gameRef)->_scene->getPath(CBPoint(_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; + ((CAdGame *)_gameRef)->addSentence(_sentence); + } + } + } else { + _currentSprite = _tempSprite2; + ((CAdGame *)_gameRef)->addSentence(_sentence); + } + } + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_READY: + if (!_animSprite && !_animSprite2) { + if (_sprite) _currentSprite = _sprite; + else { + if (_standSprite) { + _currentSprite = _standSprite->getSprite(_dir); + } else { + CAdSpriteSet *Anim = getAnimByName(_idleAnimName); + if (Anim) _currentSprite = Anim->getSprite(_dir); + } + } + } + break; + default: + error("AdActor::Update - Unhandled enum"); + } + + + if (_currentSprite && !already_moved) { + _currentSprite->GetCurrentFrame(_zoomable ? ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((CAdGame *)_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 CAdActor::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(CBPoint(_posX, _posY), *_path->getCurrent()); + } else { + if (_afterWalkDir != DI_NONE) turnTo(_afterWalkDir); + else _state = STATE_READY; + } +} + + +////////////////////////////////////////////////////////////////////////// +void CAdActor::getNextStep() { + if (_walkSprite) { + _currentSprite = _walkSprite->getSprite(_dir); + } else { + CAdSpriteSet *Anim = getAnimByName(_walkAnimName); + if (Anim) _currentSprite = Anim->getSprite(_dir); + } + + if (!_currentSprite) return; + + _currentSprite->GetCurrentFrame(_zoomable ? ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((CAdGame *)_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 (((CAdGame *)_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(CBPoint(_posX, _posY), *_path->getCurrent()); + } +} + + +////////////////////////////////////////////////////////////////////////// +void CAdActor::initLine(CBPoint startPt, CBPoint 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 CAdActor::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); + CScValue *Val = stack->pop(); + if (!Val->isNative()) { + script->runtimeError("actor.%s method accepts an entity refrence only", name); + stack->pushNULL(); + return STATUS_OK; + } + CAdObject *Obj = (CAdObject *)Val->getNative(); + if (!Obj || Obj->_type != OBJECT_ENTITY) { + script->runtimeError("actor.%s method accepts an entity refrence only", name); + stack->pushNULL(); + return STATUS_OK; + } + CAdEntity *Ent = (CAdEntity *)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; + CScValue *val = stack->pop(); + + // turn to object? + if (val->isNative() && _gameRef->validObject((CBObject *)val->getNative())) { + CBObject *obj = (CBObject *)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 (int i = 0; i < _anims.getSize(); i++) { + if (scumm_stricmp(_anims[i]->_name, 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.removeAt(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 CAdTalkHolder::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdActor::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 CAdTalkHolder::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdActor::scSetProperty(const char *name, CScValue *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 CAdTalkHolder::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdActor::scToString() { + return "[actor object]"; +} + + +////////////////////////////////////////////////////////////////////////// +CBSprite *CAdActor::getTalkStance(const char *stance) { + // forced stance? + if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { + _forcedTalkAnimUsed = true; + delete _animSprite; + _animSprite = new CBSprite(_gameRef, this); + if (_animSprite) { + bool res = _animSprite->loadFile(_forcedTalkAnimName); + if (DID_FAIL(res)) { + _gameRef->LOG(res, "CAdActor::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", _name, _forcedTalkAnimName); + delete _animSprite; + _animSprite = NULL; + } else return _animSprite; + } + } + + // old way + if (_talkSprites.getSize() > 0 || _talkSpritesEx.getSize() > 0) + return getTalkStanceOld(stance); + + // new way + CBSprite *ret = NULL; + + // do we have an animation with this name? + CAdSpriteSet *Anim = getAnimByName(stance); + if (Anim) ret = Anim->getSprite(_dir); + + // not - get a random talk + if (!ret) { + CBArray TalkAnims; + for (int i = 0; i < _anims.getSize(); i++) { + if (_talkAnimName.compareToIgnoreCase(_anims[i]->_name) == 0) + TalkAnims.add(_anims[i]); + } + + if (TalkAnims.getSize() > 0) { + int rnd = g_wintermute->randInt(0, TalkAnims.getSize() - 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; +} + +////////////////////////////////////////////////////////////////////////// +CBSprite *CAdActor::getTalkStanceOld(const char *stance) { + CBSprite *ret = NULL; + + if (stance != NULL) { + // search special stances + for (int i = 0; i < _talkSpritesEx.getSize(); i++) { + if (scumm_stricmp(_talkSpritesEx[i]->_name, stance) == 0) { + ret = _talkSpritesEx[i]->getSprite(_dir); + break; + } + } + if (ret == NULL) { + // search generic stances + for (int i = 0; i < _talkSprites.getSize(); i++) { + if (scumm_stricmp(_talkSprites[i]->_name, stance) == 0) { + ret = _talkSprites[i]->getSprite(_dir); + break; + } + } + } + } + + // not a valid stance? get a random one + if (ret == NULL) { + if (_talkSprites.getSize() < 1) ret = _standSprite->getSprite(_dir); + else { + // TODO: remember last + int rnd = g_wintermute->randInt(0, _talkSprites.getSize() - 1); + ret = _talkSprites[rnd]->getSprite(_dir); + } + } + + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdActor::persist(CBPersistMgr *persistMgr) { + CAdTalkHolder::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 CAdActor::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 CAdActor::getHeight() { + // if no current sprite is set, set some + if (_currentSprite == NULL) { + if (_standSprite) _currentSprite = _standSprite->getSprite(_dir); + else { + CAdSpriteSet *Anim = getAnimByName(_idleAnimName); + if (Anim) _currentSprite = Anim->getSprite(_dir); + } + } + // and get height + return CAdTalkHolder::getHeight(); +} + + +////////////////////////////////////////////////////////////////////////// +CAdSpriteSet *CAdActor::getAnimByName(const Common::String &animName) { + for (int i = 0; i < _anims.getSize(); i++) { + if (animName.compareToIgnoreCase(_anims[i]->_name) == 0) + return _anims[i]; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdActor::mergeAnims(const char *animsFilename) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ANIMATION) + TOKEN_TABLE_END + + + byte *fileBuffer = _gameRef->_fileManager->readWholeFile(animsFilename); + if (fileBuffer == NULL) { + _gameRef->LOG(0, "CAdActor::MergeAnims failed for file '%s'", animsFilename); + return STATUS_FAILED; + } + + byte *buffer = fileBuffer; + byte *params; + int cmd; + CBParser parser(_gameRef); + + bool Ret = STATUS_OK; + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_ANIMATION: { + CAdSpriteSet *Anim = new CAdSpriteSet(_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 CAdActor::playAnim(const char *filename) { + // if we have an anim with this name, use it + CAdSpriteSet *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 CAdTalkHolder::playAnim(filename); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/ad/ad_actor.h b/engines/wintermute/ad/ad_actor.h new file mode 100644 index 0000000000..ca79f638d9 --- /dev/null +++ b/engines/wintermute/ad/ad_actor.h @@ -0,0 +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_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/base/base_point.h" // Added by ClassView +#include "engines/wintermute/persistent.h" +#include "common/str.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +namespace WinterMute { +class CAdSpriteSet; +class CAdPath; +class CAdActor : public CAdTalkHolder { +public: + TDirection angleToDirection(int angle); + DECLARE_PERSISTENT(CAdActor, CAdTalkHolder) + virtual int getHeight(); + CBSprite *getTalkStance(const char *stance); + virtual void goTo(int x, int y, TDirection afterWalkDir = DI_NONE); + CBPoint *_targetPoint; + virtual bool update(); + virtual bool display(); + TDirection _targetDir; + TDirection _afterWalkDir; + virtual void turnTo(TDirection dir); + CAdPath *_path; + CAdSpriteSet *_walkSprite; + CAdSpriteSet *_standSprite; + CAdSpriteSet *_turnLeftSprite; + CAdSpriteSet *_turnRightSprite; + CBArray _talkSprites; + CBArray _talkSpritesEx; + TDirection _dir; + CAdActor(CBGame *inGame/*=NULL*/); + virtual ~CAdActor(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + + // new anim system + Common::String _talkAnimName; + Common::String _idleAnimName; + Common::String _walkAnimName; + Common::String _turnLeftAnimName; + Common::String _turnRightAnimName; + CBArray _anims; + virtual bool playAnim(const char *filename); + CAdSpriteSet *getAnimByName(const Common::String &animName); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + +private: + bool setDefaultAnimNames(); + CBSprite *getTalkStanceOld(const char *stance); + bool mergeAnims(const char *animsFilename); + CBSprite *_animSprite2; + + void initLine(CBPoint startPt, CBPoint endPt); + void getNextStep(); + void followPath(); + double _pFStepX; + double _pFStepY; + double _pFX; + double _pFY; + int _pFCount; +}; + +} // end of namespace WinterMute + +#endif // WINTERMUTE_ADACTOR_H diff --git a/engines/wintermute/ad/ad_entity.cpp b/engines/wintermute/ad/ad_entity.cpp new file mode 100644 index 0000000000..5f32017264 --- /dev/null +++ b/engines/wintermute/ad/ad_entity.cpp @@ -0,0 +1,1027 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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 "common/str.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdEntity, false) + +////////////////////////////////////////////////////////////////////////// +CAdEntity::CAdEntity(CBGame *inGame): CAdTalkHolder(inGame) { + _type = OBJECT_ENTITY; + _subtype = ENTITY_NORMAL; + _region = NULL; + _item = NULL; + + _walkToX = _walkToY = 0; + _walkToDir = DI_NONE; + + _theora = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdEntity::~CAdEntity() { + _gameRef->unregisterObject(_region); + + delete _theora; + _theora = NULL; + + delete[] _item; + _item = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdEntity::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdEntity::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdEntity::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; + CBParser parser(_gameRef); + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ENTITY) { + _gameRef->LOG(0, "'ENTITY' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + CAdGame *adGame = (CAdGame *)_gameRef; + CBSprite *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 CBSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params))) cmd = PARSERR_GENERIC; + else _sprite = spr; + } + break; + + case TOKEN_TALK: { + spr = new CBSprite(_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 CBSprite(_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 CBSprite(_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; + CBRegion *rgn = new CBRegion(_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; + CBRegion *rgn = new CBRegion(_gameRef); + CBRegion *crgn = new CBRegion(_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; + CAdWaypointGroup *wpt = new CAdWaypointGroup(_gameRef); + CAdWaypointGroup *cwpt = new CAdWaypointGroup(_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 CBSprite(_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.", _name); + } + + 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 && ((CAdGame *)_gameRef)->isItemTaken(_item)) _active = false; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdEntity::display() { + if (_active) { + updateSounds(); + + uint32 Alpha; + if (_alphaColor != 0) Alpha = _alphaColor; + else Alpha = _shadowable ? ((CAdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY) : 0xFFFFFFFF; + + float ScaleX, ScaleY; + getScale(&ScaleX, &ScaleY); + + float Rotate; + if (_rotatable) { + if (_rotateValid) Rotate = _rotate; + else Rotate = ((CAdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; + } else Rotate = 0.0f; + + + bool Reg = _registrable; + if (_ignoreItems && ((CAdGame *)_gameRef)->_selectedItem) Reg = false; + + if (_region && (Reg || _editorAlwaysRegister)) { + _gameRef->_renderer->_rectList.add(new CBActiveRect(_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 CAdEntity::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; + } + ((CAdGame *)_gameRef)->addSentence(_sentence); + } + } else { + _currentSprite = _tempSprite2; + ((CAdGame *)_gameRef)->addSentence(_sentence); + } + } + break; + default: // Silence unhandled enum-warning + break; + } + + + if (_currentSprite) { + _currentSprite->GetCurrentFrame(_zoomable ? ((CAdGame *)_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 CAdEntity::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); + CScValue *valAlpha = stack->pop(); + int startTime = stack->pop()->getInt(); + + delete _theora; + _theora = new CVidTheoraPlayer(_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(m_Scale>=0) m_Theora->m_PlayZoom = m_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 CBRegion(_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 CAdTalkHolder::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdEntity::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 CAdTalkHolder::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdEntity::scSetProperty(const char *name, CScValue *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 CAdTalkHolder::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdEntity::scToString() { + return "[entity object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdEntity::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "ENTITY {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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); + + int i; + + for (i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + if (_subtype == ENTITY_NORMAL && _sprite && _sprite->_filename) + buffer->putTextIndent(indent + 2, "SPRITE=\"%s\"\n", _sprite->_filename); + + if (_subtype == ENTITY_SOUND && _sFX && _sFX->_soundFilename) { + buffer->putTextIndent(indent + 2, "SOUND=\"%s\"\n", _sFX->_soundFilename); + 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->_filename) + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); + + if (_cursor && _cursor->_filename) + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); + + CAdTalkHolder::saveAsText(buffer, indent + 2); + + if (_region) _region->saveAsText(buffer, indent + 2); + + if (_scProp) _scProp->saveAsText(buffer, indent + 2); + + CAdObject::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CAdEntity::getHeight() { + if (_region && !_sprite) { + return _region->_rect.bottom - _region->_rect.top; + } else { + if (_currentSprite == NULL) _currentSprite = _sprite; + return CAdObject::getHeight(); + } +} + + +////////////////////////////////////////////////////////////////////////// +void CAdEntity::updatePosition() { + if (_region && !_sprite) { + _posX = _region->_rect.left + (_region->_rect.right - _region->_rect.left) / 2; + _posY = _region->_rect.bottom; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdEntity::persist(CBPersistMgr *persistMgr) { + CAdTalkHolder::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 CAdEntity::setItem(const char *itemName) { + CBUtils::setString(&_item, itemName); +} + +////////////////////////////////////////////////////////////////////////// +bool CAdEntity::setSprite(const char *filename) { + bool setCurrent = false; + if (_currentSprite == _sprite) { + _currentSprite = NULL; + setCurrent = true; + } + + delete _sprite; + _sprite = NULL; + CBSprite *spr = new CBSprite(_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 new file mode 100644 index 0000000000..8b67d27c1f --- /dev/null +++ b/engines/wintermute/ad/ad_entity.h @@ -0,0 +1,68 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADENTITY_H +#define WINTERMUTE_ADENTITY_H + +#include "engines/wintermute/ad/ad_talk_holder.h" + +namespace WinterMute { +class CVidTheoraPlayer; +class CAdEntity : public CAdTalkHolder { +public: + CVidTheoraPlayer *_theora; + bool setSprite(const char *filename); + int _walkToX; + int _walkToY; + TDirection _walkToDir; + void setItem(const char *itemName); + char *_item; + DECLARE_PERSISTENT(CAdEntity, CAdTalkHolder) + void updatePosition(); + virtual int getHeight(); + CBRegion *_region; + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + virtual bool update(); + virtual bool display(); + CAdEntity(CBGame *inGame); + virtual ~CAdEntity(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + TEntityType _subtype; + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..69cda25f29 --- /dev/null +++ b/engines/wintermute/ad/ad_game.cpp @@ -0,0 +1,2061 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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/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 "common/str.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdGame, true) + +////////////////////////////////////////////////////////////////////////// +CAdGame::CAdGame(): CBGame() { + _responseBox = NULL; + _inventoryBox = NULL; + + _scene = new CAdScene(_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 CAdObject(this); + _inventoryOwner = _invObject; + + _tempDisableSaveState = false; + _itemsFile = NULL; + + _smartItemCursor = false; + + addSpeechDir("speech"); +} + + +////////////////////////////////////////////////////////////////////////// +CAdGame::~CAdGame() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::cleanup() { + int i; + + for (i = 0; i < _objects.getSize(); i++) { + unregisterObject(_objects[i]); + _objects[i] = NULL; + } + _objects.removeAll(); + + + for (i = 0; i < _dlgPendingBranches.getSize(); i++) { + delete [] _dlgPendingBranches[i]; + } + _dlgPendingBranches.removeAll(); + + for (i = 0; i < _speechDirs.getSize(); i++) { + delete [] _speechDirs[i]; + } + _speechDirs.removeAll(); + + + unregisterObject(_scene); + _scene = NULL; + + // remove items + for (i = 0; i < _items.getSize(); i++) _gameRef->unregisterObject(_items[i]); + _items.removeAll(); + + + // clear remaining inventories + delete _invObject; + _invObject = NULL; + + for (i = 0; i < _inventories.getSize(); i++) { + delete _inventories[i]; + } + _inventories.removeAll(); + + + 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 (i = 0; i < _sceneStates.getSize(); i++) delete _sceneStates[i]; + _sceneStates.removeAll(); + + for (i = 0; i < _responsesBranch.getSize(); i++) delete _responsesBranch[i]; + _responsesBranch.removeAll(); + + for (i = 0; i < _responsesGame.getSize(); i++) delete _responsesGame[i]; + _responsesGame.removeAll(); + + return CBGame::cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::initLoop() { + if (_scheduledScene && _transMgr->isReady()) { + changeScene(_scheduledScene, _scheduledFadeIn); + delete[] _scheduledScene; + _scheduledScene = NULL; + + _gameRef->_activeObject = NULL; + } + + + bool res; + res = CBGame::initLoop(); + if (DID_FAIL(res)) return res; + + if (_scene) res = _scene->initLoop(); + + _sentences.removeAll(); + + return res; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::addObject(CAdObject *object) { + _objects.add(object); + return registerObject(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::removeObject(CAdObject *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 (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i] == object) { + _objects.removeAt(i); + break; + } + } + return unregisterObject(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::changeScene(const char *filename, bool fadeIn) { + if (_scene == NULL) { + _scene = new CAdScene(_gameRef); + registerObject(_scene); + } else { + _scene->applyEvent("SceneShutdown", true); + + setPrevSceneName(_scene->_name); + setPrevSceneFilename(_scene->_filename); + + if (!_tempDisableSaveState) _scene->saveState(); + _tempDisableSaveState = false; + } + + if (_scene) { + // reset objects + for (int i = 0; i < _objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 CAdGame::addSentence(CAdSentence *sentence) { + _sentences.add(sentence); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::displaySentences(bool frozen) { + for (int i = 0; i < _sentences.getSize(); i++) { + if (frozen && _sentences[i]->_freezable) continue; + else _sentences[i]->display(); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CAdGame::finishSentences() { + for (int i = 0; i < _sentences.getSize(); i++) { + if (_sentences[i]->CanSkip()) { + _sentences[i]->_duration = 0; + if (_sentences[i]->_sound) _sentences[i]->_sound->stop(); + } + } +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CAdGame::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // ChangeScene + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "ChangeScene") == 0) { + stack->correctParams(3); + const char *filename = stack->pop()->getString(); + CScValue *valFadeOut = stack->pop(); + CScValue *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); + CAdActor *act = new CAdActor(_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); + CAdEntity *ent = new CAdEntity(_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); + CScValue *val = stack->pop(); + CAdObject *obj = (CAdObject *)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); + CScValue *val = stack->pop(); + + CAdEntity *ent = new CAdEntity(_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); + CScValue *val = stack->pop(); + + CAdItem *item = new CAdItem(_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); + CScValue *val = stack->pop(); + + CAdItem *item = NULL; + if (val->isNative()) item = (CAdItem *)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); + CScValue *val = stack->pop(); + + CAdItem *item = NULL; + if (val->isInt()) { + int index = val->getInt(); + if (index >= 0 && index < _items.getSize()) 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(); + CScValue *val1 = stack->pop(); + CScValue *val2 = stack->pop(); + CScValue *val3 = stack->pop(); + CScValue *val4 = stack->pop(); + + if (_responseBox) { + CAdResponse *res = new CAdResponse(_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.getSize() == 0) { + stack->pushNULL(); + return STATUS_OK; + } + + + if (_responseBox->_responses.getSize() == 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.getSize()); + } 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); + CScValue *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; + CScValue *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.getSize() > 0) { + stack->pushString(_dlgPendingBranches[_dlgPendingBranches.getSize() - 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); + + CScValue *val = stack->pop(); + if (!val->isNULL()) { + for (int i = 0; i < _inventories.getSize(); i++) { + CAdInventory *Inv = _inventories[i]; + + for (int j = 0; j < Inv->_takenItems.getSize(); j++) { + if (val->getNative() == Inv->_takenItems[j]) { + stack->pushBool(true); + return STATUS_OK; + } else if (scumm_stricmp(val->getString(), Inv->_takenItems[j]->_name) == 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 CAdResponseBox(_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 CAdInventoryBox(_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 CBViewport(_gameRef); + if (_sceneViewport) _sceneViewport->setRect(x, y, x + width, y + height); + + stack->pushBool(true); + + return STATUS_OK; + } + + + else return CBGame::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdGame::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.getSize()); + 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 CBGame::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::scSetProperty(const char *name, CScValue *value) { + + ////////////////////////////////////////////////////////////////////////// + // SelectedItem + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SelectedItem") == 0) { + if (value->isNULL()) _selectedItem = NULL; + else { + if (value->isNative()) { + _selectedItem = NULL; + for (int i = 0; i < _items.getSize(); i++) { + if (_items[i] == value->getNative()) { + _selectedItem = (CAdItem *)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 { + CBObject *Obj = (CBObject *)value->getNative(); + if (Obj == this) _inventoryOwner = _invObject; + else if (_gameRef->validObject(Obj)) _inventoryOwner = (CAdObject *)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 CBUtils::setString(&_startupScene, value->getString()); + + return STATUS_OK; + } + + else return CBGame::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name) { + CScValue *this_obj; + + ////////////////////////////////////////////////////////////////////////// + // Actor + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Actor") == 0) { + stack->correctParams(0); + this_obj = thisStack->getTop(); + + this_obj->setNative(new CAdActor(_gameRef)); + stack->pushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // Entity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Entity") == 0) { + stack->correctParams(0); + this_obj = thisStack->getTop(); + + this_obj->setNative(new CAdEntity(_gameRef)); + stack->pushNULL(); + } + + + ////////////////////////////////////////////////////////////////////////// + // call parent + else return CBGame::ExternalCall(script, stack, thisStack, name); + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::showCursor() { + if (_cursorHidden) return STATUS_OK; + + if (_selectedItem && _gameRef->_state == GAME_RUNNING && _stateEx == GAME_NORMAL && _interactive) { + if (_selectedItem->_cursorCombined) { + CBSprite *origLastCursor = _lastCursor; + CBGame::showCursor(); + _lastCursor = origLastCursor; + } + if (_activeObject && _selectedItem->_cursorHover && _activeObject->getExtendedFlag("usable")) { + if (!_smartItemCursor || _activeObject->canHandleEvent(_selectedItem->_name)) + return drawCursor(_selectedItem->_cursorHover); + else + return drawCursor(_selectedItem->_cursorNormal); + } else return drawCursor(_selectedItem->_cursorNormal); + } else return CBGame::showCursor(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::loadFile(const char *filename) { + byte *buffer = _fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdGame::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdGame::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; + CBParser parser(_gameRef); + + 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(CBGame::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 CAdResponseBox(_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 CAdInventoryBox(_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; + CBUtils::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 CBViewport(_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: + CBUtils::setString(&_startupScene, (char *)params2); + break; + + case TOKEN_DEBUG_STARTUP_SCENE: + CBUtils::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 CAdGame::persist(CBPersistMgr *persistMgr) { + if (!persistMgr->_saving) cleanup(); + CBGame::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->_saving) _initialScene = false; + + persistMgr->transfer(TMEMBER(_startupScene)); + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::loadGame(const char *filename) { + bool ret = CBGame::loadGame(filename); + if (DID_SUCCEED(ret)) CSysClassRegistry::getInstance()->enumInstances(afterLoadRegion, "CAdRegion", NULL); + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::initAfterLoad() { + CBGame::initAfterLoad(); + CSysClassRegistry::getInstance()->enumInstances(afterLoadScene, "CAdScene", NULL); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CAdGame::afterLoadScene(void *scene, void *data) { + ((CAdScene *)scene)->afterLoad(); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdGame::setPrevSceneName(const char *name) { + delete[] _prevSceneName; + _prevSceneName = NULL; + if (name) { + _prevSceneName = new char[strlen(name) + 1]; + if (_prevSceneName) strcpy(_prevSceneName, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +void CAdGame::setPrevSceneFilename(const char *name) { + delete[] _prevSceneFilename; + _prevSceneFilename = NULL; + if (name) { + _prevSceneFilename = new char[strlen(name) + 1]; + if (_prevSceneFilename) strcpy(_prevSceneFilename, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::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 CAdGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor) { + CBGame::getVersion(verMajor, verMinor, NULL, NULL); + + if (extMajor) *extMajor = 0; + if (extMinor) *extMinor = 0; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::loadItemsFile(const char *filename, bool merge) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdGame::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 CAdGame::loadItemsBuffer(byte *buffer, bool merge) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ITEM) + TOKEN_TABLE_END + + byte *params; + int cmd; + CBParser parser(_gameRef); + + if (!merge) { + while (_items.getSize() > 0) deleteItem(_items[0]); + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_ITEM: { + CAdItem *item = new CAdItem(_gameRef); + if (item && !DID_FAIL(item->loadBuffer(params, false))) { + // delete item with the same name, if exists + if (merge) { + CAdItem *PrevItem = getItemByName(item->_name); + 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; +} + + +////////////////////////////////////////////////////////////////////////// +CAdSceneState *CAdGame::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 (int i = 0; i < _sceneStates.getSize(); i++) { + if (scumm_stricmp(_sceneStates[i]->_filename, filenameCor) == 0) { + delete [] filenameCor; + return _sceneStates[i]; + } + } + + if (saving) { + CAdSceneState *ret = new CAdSceneState(_gameRef); + ret->setFilename(filenameCor); + + _sceneStates.add(ret); + + delete [] filenameCor; + return ret; + } else { + delete [] filenameCor; + return NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::windowLoadHook(CUIWindow *win, char **buffer, char **params) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ENTITY_CONTAINER) + TOKEN_TABLE_END + + int cmd = PARSERR_GENERIC; + CBParser parser(_gameRef); + + cmd = parser.getCommand(buffer, commands, params); + switch (cmd) { + case TOKEN_ENTITY_CONTAINER: { + CUIEntity *ent = new CUIEntity(_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 CAdGame::windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name) { + if (strcmp(name, "CreateEntityContainer") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + + CUIEntity *ent = new CUIEntity(_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 CAdGame::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 CAdGame::endDlgBranch(const char *branchName, const char *scriptName, const char *eventName) { + char *name = NULL; + bool deleteName = false; + if (branchName == NULL && _dlgPendingBranches.getSize() > 0) { + name = _dlgPendingBranches[_dlgPendingBranches.getSize() - 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.getSize() - 1; i >= 0; i--) { + if (scumm_stricmp(name, _dlgPendingBranches[i]) == 0) { + startIndex = i; + break; + } + } + if (startIndex >= 0) { + for (int i = startIndex; i < _dlgPendingBranches.getSize(); i++) { + //ClearBranchResponses(_dlgPendingBranches[i]); + delete [] _dlgPendingBranches[i]; + _dlgPendingBranches[i] = NULL; + } + _dlgPendingBranches.removeAt(startIndex, _dlgPendingBranches.getSize() - startIndex); + } + + // dialogue is over, forget selected responses + if (_dlgPendingBranches.getSize() == 0) { + for (int i = 0; i < _responsesBranch.getSize(); i++) delete _responsesBranch[i]; + _responsesBranch.removeAll(); + } + + if (deleteName) delete [] name; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::clearBranchResponses(char *name) { + for (int i = 0; i < _responsesBranch.getSize(); i++) { + if (scumm_stricmp(name, _responsesBranch[i]->_context) == 0) { + delete _responsesBranch[i]; + _responsesBranch.removeAt(i); + i--; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::addBranchResponse(int ID) { + if (branchResponseUsed(ID)) return STATUS_OK; + CAdResponseContext *r = new CAdResponseContext(_gameRef); + r->_iD = ID; + r->setContext(_dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL); + _responsesBranch.add(r); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::branchResponseUsed(int ID) { + char *Context = _dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL; + for (int i = 0; i < _responsesBranch.getSize(); 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 CAdGame::addGameResponse(int ID) { + if (gameResponseUsed(ID)) return STATUS_OK; + CAdResponseContext *r = new CAdResponseContext(_gameRef); + r->_iD = ID; + r->setContext(_dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL); + _responsesGame.add(r); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::gameResponseUsed(int ID) { + char *Context = _dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL; + for (int i = 0; i < _responsesGame.getSize(); i++) { + CAdResponseContext *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 CAdGame::resetResponse(int ID) { + char *Context = _dlgPendingBranches.getSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.getSize() - 1] : NULL; + + int i; + + for (i = 0; i < _responsesGame.getSize(); i++) { + if (_responsesGame[i]->_iD == ID) { + if ((Context == NULL && _responsesGame[i]->_context == NULL) || scumm_stricmp(Context, _responsesGame[i]->_context) == 0) { + delete _responsesGame[i]; + _responsesGame.removeAt(i); + break; + } + } + } + + for (i = 0; i < _responsesBranch.getSize(); i++) { + if (_responsesBranch[i]->_iD == ID) { + if ((Context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(Context, _responsesBranch[i]->_context) == 0) { + delete _responsesBranch[i]; + _responsesBranch.removeAt(i); + break; + } + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::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(); + if (_indicatorDisplay) 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 CAdGame::registerInventory(CAdInventory *inv) { + for (int i = 0; i < _inventories.getSize(); i++) { + if (_inventories[i] == inv) return STATUS_OK; + } + registerObject(inv); + _inventories.add(inv); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::unregisterInventory(CAdInventory *inv) { + for (int i = 0; i < _inventories.getSize(); i++) { + if (_inventories[i] == inv) { + unregisterObject(_inventories[i]); + _inventories.removeAt(i); + return STATUS_OK; + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::isItemTaken(char *itemName) { + for (int i = 0; i < _inventories.getSize(); i++) { + CAdInventory *Inv = _inventories[i]; + + for (int j = 0; j < Inv->_takenItems.getSize(); j++) { + if (scumm_stricmp(itemName, Inv->_takenItems[j]->_name) == 0) { + return true; + } + } + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +CAdItem *CAdGame::getItemByName(const char *name) { + for (int i = 0; i < _items.getSize(); i++) { + if (scumm_stricmp(_items[i]->_name, name) == 0) return _items[i]; + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::addItem(CAdItem *item) { + _items.add(item); + return _gameRef->registerObject(item); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::resetContent() { + // clear pending dialogs + for (int i = 0; i < _dlgPendingBranches.getSize(); i++) { + delete [] _dlgPendingBranches[i]; + } + _dlgPendingBranches.removeAll(); + + + // clear inventories + for (int i = 0; i < _inventories.getSize(); i++) { + _inventories[i]->_takenItems.removeAll(); + } + + // clear scene states + for (int i = 0; i < _sceneStates.getSize(); i++) delete _sceneStates[i]; + _sceneStates.removeAll(); + + // clear once responses + for (int i = 0; i < _responsesBranch.getSize(); i++) delete _responsesBranch[i]; + _responsesBranch.removeAll(); + + // clear once game responses + for (int i = 0; i < _responsesGame.getSize(); i++) delete _responsesGame[i]; + _responsesGame.removeAll(); + + // reload inventory items + if (_itemsFile) loadItemsFile(_itemsFile); + + _tempDisableSaveState = true; + + return CBGame::resetContent(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::deleteItem(CAdItem *item) { + if (!item) return STATUS_FAILED; + + if (_selectedItem == item) _selectedItem = NULL; + _scene->handleItemAssociations(item->_name, false); + + // remove from all inventories + for (int i = 0; i < _inventories.getSize(); i++) { + _inventories[i]->removeItem(item); + } + + // remove object + for (int i = 0; i < _items.getSize(); i++) { + if (_items[i] == item) { + unregisterObject(_items[i]); + _items.removeAt(i); + break; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::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 (int i = 0; i < _speechDirs.getSize(); i++) { + if (scumm_stricmp(_speechDirs[i], temp) == 0) { + delete [] temp; + return STATUS_OK; + } + } + _speechDirs.add(temp); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::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 (int i = 0; i < _speechDirs.getSize(); i++) { + if (scumm_stricmp(_speechDirs[i], temp) == 0) { + delete [] _speechDirs[i]; + _speechDirs.removeAt(i); + Found = true; + break; + } + } + delete [] temp; + + if (Found) return STATUS_OK; + else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +char *CAdGame::findSpeechFile(char *stringID) { + char *ret = new char[MAX_PATH_LENGTH]; + + for (int i = 0; i < _speechDirs.getSize(); i++) { + sprintf(ret, "%s%s.ogg", _speechDirs[i], stringID); + Common::SeekableReadStream *file = _fileManager->openFile(ret); // TODO: Replace with hasFile + if (file) { + _fileManager->closeFile(file); + return ret; + } + + sprintf(ret, "%s%s.wav", _speechDirs[i], stringID); + file = _fileManager->openFile(ret); + if (file) { + _fileManager->closeFile(file); + return ret; + } + } + delete [] ret; + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::validMouse() { + Point32 pos; + CBPlatform::getCursorPos(&pos); + + return _renderer->pointInViewport(&pos); +} + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::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; + CBPlatform::setCapture(/*_renderer->_window*/); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::onMouseLeftUp() { + if (_activeObject) _activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT); + + CBPlatform::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 CAdGame::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 CAdGame::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 CAdGame::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 CAdGame::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->_name) ? _scene->_name : "???", _prevSceneName ? _prevSceneName : "???"); + _systemFont->drawText((byte *)str, 0, 110, _renderer->_width, TAL_RIGHT); + } + return CBGame::displayDebugInfo(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdGame::onScriptShutdown(CScScript *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 new file mode 100644 index 0000000000..09b3e09df0 --- /dev/null +++ b/engines/wintermute/ad/ad_game.h @@ -0,0 +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 + */ +#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 CAdItem; +class CAdInventory; +class CAdSceneState; +class CAdScene; +class CAdItem; +class CAdObject; +class CAdSentence; +class CAdInventoryBox; +class CAdResponseContext; +class CAdResponseBox; +class CAdGame : public CBGame { +public: + virtual bool onScriptShutdown(CScScript *script); + + virtual bool onMouseLeftDown(); + virtual bool onMouseLeftUp(); + virtual bool onMouseLeftDblClick(); + virtual bool onMouseRightDown(); + virtual bool onMouseRightUp(); + + virtual bool displayDebugInfo(); + + + virtual bool initAfterLoad(); + static void afterLoadScene(void *scene, void *data); + + bool _smartItemCursor; + + CBArray _speechDirs; + bool addSpeechDir(const char *dir); + bool removeSpeechDir(const char *dir); + char *findSpeechFile(char *StringID); + + bool deleteItem(CAdItem *Item); + char *_itemsFile; + bool _tempDisableSaveState; + virtual bool resetContent(); + bool addItem(CAdItem *item); + CAdItem *getItemByName(const char *name); + CBArray _items; + CAdObject *_inventoryOwner; + bool isItemTaken(char *itemName); + bool registerInventory(CAdInventory *inv); + bool unregisterInventory(CAdInventory *inv); + + CAdObject *_invObject; + CBArray _inventories; + virtual bool displayContent(bool update = true, bool displayAll = false); + char *_debugStartupScene; + char *_startupScene; + bool _initialScene; + 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(CUIWindow *win, char **buf, char **params); + virtual bool windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name); + + CAdSceneState *getSceneState(const char *filename, bool saving); + CBViewport *_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); + char *_scheduledScene; + bool _scheduledFadeIn; + void setPrevSceneName(const char *name); + void setPrevSceneFilename(const char *name); + char *_prevSceneName; + char *_prevSceneFilename; + virtual bool loadGame(const char *filename); + CAdItem *_selectedItem; + bool cleanup(); + DECLARE_PERSISTENT(CAdGame, CBGame) + + void finishSentences(); + bool showCursor(); + TGameStateEx _stateEx; + CAdResponseBox *_responseBox; + CAdInventoryBox *_inventoryBox; + bool displaySentences(bool frozen); + void addSentence(CAdSentence *sentence); + bool changeScene(const char *filename, bool fadeIn); + bool removeObject(CAdObject *object); + bool addObject(CAdObject *object); + CAdScene *_scene; + bool initLoop(); + CAdGame(); + virtual ~CAdGame(); + CBArray _objects; + CBArray _sentences; + + CBArray _sceneStates; + CBArray _dlgPendingBranches; + + CBArray _responsesBranch; + CBArray _responsesGame; + + 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); + + + virtual bool ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + bool validMouse(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/ad/ad_inventory.cpp b/engines/wintermute/ad/ad_inventory.cpp new file mode 100644 index 0000000000..cfbc9e5029 --- /dev/null +++ b/engines/wintermute/ad/ad_inventory.cpp @@ -0,0 +1,119 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CAdInventory, false) + +////////////////////////////////////////////////////////////////////////// +CAdInventory::CAdInventory(CBGame *inGame): CBObject(inGame) { + _scrollOffset = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CAdInventory::~CAdInventory() { + _takenItems.removeAll(); // ref only +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdInventory::insertItem(const char *name, const char *insertAfter) { + if (name == NULL) return STATUS_FAILED; + + CAdItem *item = ((CAdGame *)_gameRef)->getItemByName(name); + if (item == NULL) return STATUS_FAILED; + + int insertIndex = -1; + for (int i = 0; i < _takenItems.getSize(); i++) { + if (scumm_stricmp(_takenItems[i]->_name, name) == 0) { + _takenItems.removeAt(i); + i--; + continue; + } + if (insertAfter && scumm_stricmp(_takenItems[i]->_name, insertAfter) == 0) insertIndex = i + 1; + } + + + if (insertIndex == -1) _takenItems.add(item); + else _takenItems.insertAt(insertIndex, item); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdInventory::removeItem(const char *name) { + if (name == NULL) return STATUS_FAILED; + + for (int i = 0; i < _takenItems.getSize(); i++) { + if (scumm_stricmp(_takenItems[i]->_name, name) == 0) { + if (((CAdGame *)_gameRef)->_selectedItem == _takenItems[i])((CAdGame *)_gameRef)->_selectedItem = NULL; + _takenItems.removeAt(i); + return STATUS_OK; + } + } + + return STATUS_FAILED; +} + + + +////////////////////////////////////////////////////////////////////////// +bool CAdInventory::removeItem(CAdItem *item) { + if (item == NULL) return STATUS_FAILED; + + for (int i = 0; i < _takenItems.getSize(); i++) { + if (_takenItems[i] == item) { + if (((CAdGame *)_gameRef)->_selectedItem == _takenItems[i])((CAdGame *)_gameRef)->_selectedItem = NULL; + _takenItems.removeAt(i); + return STATUS_OK; + } + } + + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdInventory::persist(CBPersistMgr *persistMgr) { + + CBObject::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 new file mode 100644 index 0000000000..84d9308d5d --- /dev/null +++ b/engines/wintermute/ad/ad_inventory.h @@ -0,0 +1,52 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADINVENTORY_H +#define WINTERMUTE_ADINVENTORY_H + +#include "engines/wintermute/base/base_object.h" + +namespace WinterMute { + +class CAdItem; + +class CAdInventory : public CBObject { +public: + DECLARE_PERSISTENT(CAdInventory, CBObject) + bool removeItem(const char *name); + bool removeItem(CAdItem *Item); + bool insertItem(const char *name, const char *insertAfter = NULL); + CAdInventory(CBGame *inGame); + virtual ~CAdInventory(); + CBArray _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 new file mode 100644 index 0000000000..abe8676376 --- /dev/null +++ b/engines/wintermute/ad/ad_inventory_box.cpp @@ -0,0 +1,372 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CAdInventoryBox, false) + +////////////////////////////////////////////////////////////////////////// +CAdInventoryBox::CAdInventoryBox(CBGame *inGame): CBObject(inGame) { + _itemsArea.setEmpty(); + _scrollOffset = 0; + _spacing = 0; + _itemWidth = _itemHeight = 50; + _scrollBy = 1; + + _window = NULL; + _closeButton = NULL; + + _hideSelected = false; + + _visible = false; + _exclusive = false; +} + + +////////////////////////////////////////////////////////////////////////// +CAdInventoryBox::~CAdInventoryBox() { + _gameRef->unregisterObject(_window); + _window = NULL; + + delete _closeButton; + _closeButton = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdInventoryBox::listen(CBScriptHolder *param1, uint32 param2) { + CUIObject *obj = (CUIObject *)param1; + + switch (obj->_type) { + case UI_BUTTON: + if (scumm_stricmp(obj->_name, "close") == 0) { + _visible = false; + } else if (scumm_stricmp(obj->_name, "prev") == 0) { + _scrollOffset -= _scrollBy; + _scrollOffset = MAX(_scrollOffset, 0); + } else if (scumm_stricmp(obj->_name, "next") == 0) { + _scrollOffset += _scrollBy; + } else return CBObject::listen(param1, param2); + break; + default: + error("CAdInventoryBox::Listen - Unhandled enum"); + break; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdInventoryBox::display() { + CAdGame *adGame = (CAdGame *)_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 < adGame->_inventoryOwner->getInventory()->_takenItems.getSize()); + } + + + 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 < adGame->_inventoryOwner->getInventory()->_takenItems.getSize()) { + CAdItem *item = adGame->_inventoryOwner->getInventory()->_takenItems[itemIndex]; + if (item != ((CAdGame *)_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 CAdInventoryBox::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdInventoryBox::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdInventoryBox::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; + CBParser parser(_gameRef); + bool always_visible = 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 CUIWindow(_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", &always_visible); + 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 CUIButton(_gameRef); + if (_closeButton) { + _closeButton->setName("close"); + _closeButton->setListener(this, _closeButton, 0); + _closeButton->_parent = _window; + } + } + + _visible = always_visible; + + if (_window) { + for (int i = 0; i < _window->_widgets.getSize(); i++) { + if (!_window->_widgets[i]->_listenerObject) + _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdInventoryBox::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "INVENTORY_BOX\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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 + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdInventoryBox::persist(CBPersistMgr *persistMgr) { + CBObject::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 new file mode 100644 index 0000000000..09d3ef409e --- /dev/null +++ b/engines/wintermute/ad/ad_inventory_box.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * 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 CUIButton; +class CUIWindow; + +class CAdInventoryBox : public CBObject { +public: + bool _hideSelected; + DECLARE_PERSISTENT(CAdInventoryBox, CBObject) + bool _exclusive; + int _scrollBy; + int _itemHeight; + int _itemWidth; + bool _visible; + virtual bool display(); + CUIButton *_closeButton; + int _spacing; + int _scrollOffset; + Rect32 _itemsArea; + bool listen(CBScriptHolder *param1, uint32 param2); + CUIWindow *_window; + CAdInventoryBox(CBGame *inGame); + virtual ~CAdInventoryBox(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/ad/ad_item.cpp b/engines/wintermute/ad/ad_item.cpp new file mode 100644 index 0000000000..9c49a86bcb --- /dev/null +++ b/engines/wintermute/ad/ad_item.cpp @@ -0,0 +1,760 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#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(CAdItem, false) + +////////////////////////////////////////////////////////////////////////// +CAdItem::CAdItem(CBGame *inGame): CAdTalkHolder(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; +} + + +////////////////////////////////////////////////////////////////////////// +CAdItem::~CAdItem() { + delete _spriteHover; + delete _cursorNormal; + delete _cursorHover; + _spriteHover = NULL; + _cursorNormal = NULL; + _cursorHover = NULL; + + delete[] _amountString; + _amountString = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdItem::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdItem::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdItem::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; + CBParser parser(_gameRef); + + 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 CBSprite(_gameRef, this); + if (!_sprite || DID_FAIL(_sprite->loadFile((char *)params, ((CAdGame *)_gameRef)->_texItemLifeTime))) { + delete _sprite; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE_HOVER: + case TOKEN_SPRITE_HOVER: + delete _spriteHover; + _spriteHover = new CBSprite(_gameRef, this); + if (!_spriteHover || DID_FAIL(_spriteHover->loadFile((char *)params, ((CAdGame *)_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: + CBUtils::setString(&_amountString, (char *)params); + break; + + case TOKEN_TALK: { + CBSprite *spr = new CBSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params, ((CAdGame *)_gameRef)->_texTalkLifeTime))) cmd = PARSERR_GENERIC; + else _talkSprites.add(spr); + } + break; + + case TOKEN_TALK_SPECIAL: { + CBSprite *spr = new CBSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params, ((CAdGame *)_gameRef)->_texTalkLifeTime))) cmd = PARSERR_GENERIC; + else _talkSpritesEx.add(spr); + } + break; + + case TOKEN_CURSOR: + delete _cursorNormal; + _cursorNormal = new CBSprite(_gameRef); + if (!_cursorNormal || DID_FAIL(_cursorNormal->loadFile((char *)params, ((CAdGame *)_gameRef)->_texItemLifeTime))) { + delete _cursorNormal; + _cursorNormal = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_CURSOR_HOVER: + delete _cursorHover; + _cursorHover = new CBSprite(_gameRef); + if (!_cursorHover || DID_FAIL(_cursorHover->loadFile((char *)params, ((CAdGame *)_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 CAdItem::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; + } + ((CAdGame *)_gameRef)->addSentence(_sentence); + } + } else { + _currentSprite = _tempSprite2; + ((CAdGame *)_gameRef)->addSentence(_sentence); + } + } + default: + break; + } + _ready = (_state == STATE_READY); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdItem::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; + + CBFont *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 CAdItem::scCallMethod(CScScript *script, CScStack *stack, CScStack *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; + CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_spriteHover->_filename); + 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; + CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_cursorNormal->_filename); + 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; + CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_cursorHover->_filename); + 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 CAdTalkHolder::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdItem::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(_name); + 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 CAdTalkHolder::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdItem::scSetProperty(const char *name, CScValue *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 { + CBUtils::setString(&_amountString, value->getString()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorCombined + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorCombined") == 0) { + _cursorCombined = value->getBool(); + return STATUS_OK; + } + + else return CAdTalkHolder::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdItem::scToString() { + return "[item]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdItem::persist(CBPersistMgr *persistMgr) { + + CAdTalkHolder::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 CAdItem::getExtendedFlag(const char *flagName) { + if (!flagName) return false; + else if (strcmp(flagName, "usable") == 0) return true; + else return CAdObject::getExtendedFlag(flagName); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/ad/ad_item.h b/engines/wintermute/ad/ad_item.h new file mode 100644 index 0000000000..34b19a830f --- /dev/null +++ b/engines/wintermute/ad/ad_item.h @@ -0,0 +1,70 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CAdItem : public CAdTalkHolder { +public: + bool _displayAmount; + int _amount; + int _amountOffsetX; + int _amountOffsetY; + TTextAlign _amountAlign; + char *_amountString; + + + bool update(); + DECLARE_PERSISTENT(CAdItem, CAdTalkHolder) + bool display(int x, int y); + bool getExtendedFlag(const char *flagName); + bool _inInventory; + bool _cursorCombined; + CBSprite *_spriteHover; + CBSprite *_cursorNormal; + CBSprite *_cursorHover; + CAdItem(CBGame *inGame); + virtual ~CAdItem(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/ad/ad_layer.cpp b/engines/wintermute/ad/ad_layer.cpp new file mode 100644 index 0000000000..e23948ed87 --- /dev/null +++ b/engines/wintermute/ad/ad_layer.cpp @@ -0,0 +1,537 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CAdLayer, false) + +////////////////////////////////////////////////////////////////////////// +CAdLayer::CAdLayer(CBGame *inGame): CBObject(inGame) { + _main = false; + _width = _height = 0; + _active = true; + _closeUp = false; +} + + +////////////////////////////////////////////////////////////////////////// +CAdLayer::~CAdLayer() { + for (int i = 0; i < _nodes.getSize(); i++) + delete _nodes[i]; + _nodes.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdLayer::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdLayer::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdLayer::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; + CBParser parser(_gameRef); + + 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: { + CAdRegion *region = new CAdRegion(_gameRef); + CAdSceneNode *node = new CAdSceneNode(_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: { + CAdEntity *entity = new CAdEntity(_gameRef); + CAdSceneNode *node = new CAdSceneNode(_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 CAdLayer::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GetNode + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetNode") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + int node = -1; + + if (val->_type == VAL_INT) node = val->getInt(); + else { // get by name + for (int i = 0; i < _nodes.getSize(); i++) { + if ((_nodes[i]->_type == OBJECT_ENTITY && scumm_stricmp(_nodes[i]->_entity->_name, val->getString()) == 0) || + (_nodes[i]->_type == OBJECT_REGION && scumm_stricmp(_nodes[i]->_region->_name, val->getString()) == 0)) { + node = i; + break; + } + } + } + + if (node < 0 || node >= _nodes.getSize()) 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); + CScValue *val = stack->pop(); + + CAdSceneNode *node = new CAdSceneNode(_gameRef); + if (strcmp(name, "AddRegion") == 0) { + CAdRegion *region = new CAdRegion(_gameRef); + if (!val->isNULL()) region->setName(val->getString()); + node->setRegion(region); + stack->pushNative(region, true); + } else { + CAdEntity *entity = new CAdEntity(_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(); + CScValue *val = stack->pop(); + + CAdSceneNode *node = new CAdSceneNode(_gameRef); + if (strcmp(name, "InsertRegion") == 0) { + CAdRegion *region = new CAdRegion(_gameRef); + if (!val->isNULL()) region->setName(val->getString()); + node->setRegion(region); + stack->pushNative(region, true); + } else { + CAdEntity *entity = new CAdEntity(_gameRef); + if (!val->isNULL()) entity->setName(val->getString()); + node->setEntity(entity); + stack->pushNative(entity, true); + } + if (index < 0) index = 0; + if (index <= _nodes.getSize() - 1) _nodes.insertAt(index, node); + else _nodes.add(node); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteNode + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DeleteNode") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + + CAdSceneNode *toDelete = NULL; + if (val->isNative()) { + CBScriptable *temp = val->getNative(); + for (int i = 0; i < _nodes.getSize(); i++) { + if (_nodes[i]->_region == temp || _nodes[i]->_entity == temp) { + toDelete = _nodes[i]; + break; + } + } + } else { + int index = val->getInt(); + if (index >= 0 && index < _nodes.getSize()) { + toDelete = _nodes[index]; + } + } + if (toDelete == NULL) { + stack->pushBool(false); + return STATUS_OK; + } + + for (int i = 0; i < _nodes.getSize(); i++) { + if (_nodes[i] == toDelete) { + delete _nodes[i]; + _nodes[i] = NULL; + _nodes.removeAt(i); + break; + } + } + stack->pushBool(true); + return STATUS_OK; + } + + else return CBObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdLayer::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.getSize()); + 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 CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdLayer::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdLayer::scToString() { + return "[layer]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdLayer::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "LAYER {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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"); + + int i; + + for (i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + if (_scProp) _scProp->saveAsText(buffer, indent + 2); + + for (i = 0; i < _nodes.getSize(); 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("CAdLayer::SaveAsText - Unhandled enum"); + break; + } + } + + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdLayer::persist(CBPersistMgr *persistMgr) { + + CBObject::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 new file mode 100644 index 0000000000..0ccdb13ae7 --- /dev/null +++ b/engines/wintermute/ad/ad_layer.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADLAYER_H +#define WINTERMUTE_ADLAYER_H + +namespace WinterMute { +class CAdSceneNode; +class CAdLayer : public CBObject { +public: + bool _closeUp; + DECLARE_PERSISTENT(CAdLayer, CBObject) + bool _active; + int _height; + int _width; + bool _main; + CAdLayer(CBGame *inGame); + virtual ~CAdLayer(); + CBArray _nodes; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..06f9c4cf95 --- /dev/null +++ b/engines/wintermute/ad/ad_node_state.cpp @@ -0,0 +1,169 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CAdNodeState, false) + + +////////////////////////////////////////////////////////////////////////// +CAdNodeState::CAdNodeState(CBGame *inGame): CBBase(inGame) { + _name = NULL; + _active = false; + for (int i = 0; i < 7; i++) _caption[i] = NULL; + _alphaColor = 0; + _filename = NULL; + _cursor = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdNodeState::~CAdNodeState() { + 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 CAdNodeState::setName(const char *name) { + delete[] _name; + _name = NULL; + CBUtils::setString(&_name, name); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdNodeState::setFilename(const char *filename) { + delete[] _filename; + _filename = NULL; + CBUtils::setString(&_filename, filename); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdNodeState::setCursor(const char *filename) { + delete[] _cursor; + _cursor = NULL; + CBUtils::setString(&_cursor, filename); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdNodeState::persist(CBPersistMgr *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 CAdNodeState::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]); + } +} + + +////////////////////////////////////////////////////////////////////////// +char *CAdNodeState::getCaption(int caseVal) { + if (caseVal== 0) caseVal= 1; + if (caseVal< 1 || caseVal> 7 || _caption[caseVal- 1] == NULL) return ""; + else return _caption[caseVal- 1]; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdNodeState::transferEntity(CAdEntity *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->_filename) { + if (includingSprites) setFilename(entity->_sprite->_filename); + else setFilename(""); + } + if (entity->_cursor && entity->_cursor->_filename) setCursor(entity->_cursor->_filename); + _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->_filename || scumm_stricmp(entity->_sprite->_filename, _filename) != 0) + entity->setSprite(_filename); + } + if (_cursor) { + if (!entity->_cursor || !entity->_cursor->_filename || scumm_stricmp(entity->_cursor->_filename, _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 new file mode 100644 index 0000000000..186f2ebbb2 --- /dev/null +++ b/engines/wintermute/ad/ad_node_state.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADNODESTATE_H +#define WINTERMUTE_ADNODESTATE_H + +namespace WinterMute { + +class CAdEntity; + +class CAdNodeState : public CBBase { +public: + bool transferEntity(CAdEntity *entity, bool includingSprites, bool saving); + void setName(const char *name); + void setFilename(const char *filename); + void setCursor(const char *filename); + DECLARE_PERSISTENT(CAdNodeState, CBBase) + CAdNodeState(CBGame *inGame); + virtual ~CAdNodeState(); + char *_name; + bool _active; + char *_caption[7]; + void setCaption(const char *caption, int caseVal); + 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 new file mode 100644 index 0000000000..46f2e590fd --- /dev/null +++ b/engines/wintermute/ad/ad_object.cpp @@ -0,0 +1,1203 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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 "common/str.h" +#include "common/util.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdObject, false) + +////////////////////////////////////////////////////////////////////////// +CAdObject::CAdObject(CBGame *inGame): CBObject(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; +} + + +////////////////////////////////////////////////////////////////////////// +CAdObject::~CAdObject() { + _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) { + ((CAdGame *)_gameRef)->unregisterInventory(_inventory); + _inventory = NULL; + } + + if (_partEmitter) + _gameRef->unregisterObject(_partEmitter); + + + for (int i = 0; i < _attachmentsPre.getSize(); i++) { + _gameRef->unregisterObject(_attachmentsPre[i]); + } + _attachmentsPre.removeAll(); + + for (int i = 0; i < _attachmentsPost.getSize(); i++) { + _gameRef->unregisterObject(_attachmentsPost[i]); + } + _attachmentsPost.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::playAnim(const char *filename) { + delete _animSprite; + _animSprite = NULL; + _animSprite = new CBSprite(_gameRef, this); + if (!_animSprite) { + _gameRef->LOG(0, "CAdObject::PlayAnim: error creating temp sprite (object:\"%s\" sprite:\"%s\")", _name, filename); + return STATUS_FAILED; + } + bool res = _animSprite->loadFile(filename); + if (DID_FAIL(res)) { + _gameRef->LOG(res, "CAdObject::PlayAnim: error loading temp sprite (object:\"%s\" sprite:\"%s\")", _name, filename); + delete _animSprite; + _animSprite = NULL; + return res; + } + _state = STATE_PLAYING_ANIM; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::display() { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::update() { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CAdObject::scCallMethod(CScScript *script, CScStack *stack, CScStack *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(); + CScValue *soundVal = stack->pop(); + int duration = stack->pop()->getInt(); + CScValue *valStances = stack->pop(); + + const char *stances = valStances->isNULL() ? NULL : valStances->getString(); + + int align = 0; + CScValue *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); + + CAdLayer *main = ((CAdGame *)_gameRef)->_scene->_mainLayer; + bool regFound = false; + + int i; + CScValue *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.getSize(); i++) { + if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region->_name && scumm_stricmp(main->_nodes[i]->_region->_name, regionName) == 0) { + _stickRegion = main->_nodes[i]->_region; + regFound = true; + break; + } + } + } else if (val->isNative()) { + CBScriptable *obj = val->getNative(); + + for (i = 0; i < main->_nodes.getSize(); 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); + CScValue *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->_filename) stack->pushString(_font->_filename); + else stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TakeItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TakeItem") == 0) { + stack->correctParams(2); + + if (!_inventory) { + _inventory = new CAdInventory(_gameRef); + ((CAdGame *)_gameRef)->registerInventory(_inventory); + } + + CScValue *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 + ((CAdGame *)_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 CAdInventory(_gameRef); + ((CAdGame *)_gameRef)->registerInventory(_inventory); + } + + CScValue *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 + ((CAdGame *)_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 CAdInventory(_gameRef); + ((CAdGame *)_gameRef)->registerInventory(_inventory); + } + + CScValue *val = stack->pop(); + if (val->_type == VAL_STRING) { + CAdItem *item = ((CAdGame *)_gameRef)->getItemByName(val->getString()); + if (item) stack->pushNative(item, true); + else stack->pushNULL(); + } else if (val->isNULL() || val->getInt() < 0 || val->getInt() >= _inventory->_takenItems.getSize()) + 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 CAdInventory(_gameRef); + ((CAdGame *)_gameRef)->registerInventory(_inventory); + } + + CScValue *val = stack->pop(); + if (!val->isNULL()) { + for (int i = 0; i < _inventory->_takenItems.getSize(); i++) { + if (val->getNative() == _inventory->_takenItems[i]) { + stack->pushBool(true); + return STATUS_OK; + } else if (scumm_stricmp(val->getString(), _inventory->_takenItems[i]->_name) == 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(); + + CPartEmitter *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; + CAdEntity *ent = new CAdEntity(_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); + CScValue *val = stack->pop(); + bool found = false; + if (val->isNative()) { + CBScriptable *obj = val->getNative(); + for (int i = 0; i < _attachmentsPre.getSize(); i++) { + if (_attachmentsPre[i] == obj) { + found = true; + _gameRef->unregisterObject(_attachmentsPre[i]); + _attachmentsPre.removeAt(i); + i--; + } + } + for (int i = 0; i < _attachmentsPost.getSize(); i++) { + if (_attachmentsPost[i] == obj) { + found = true; + _gameRef->unregisterObject(_attachmentsPost[i]); + _attachmentsPost.removeAt(i); + i--; + } + } + } else { + const char *attachmentName = val->getString(); + for (int i = 0; i < _attachmentsPre.getSize(); i++) { + if (_attachmentsPre[i]->_name && scumm_stricmp(_attachmentsPre[i]->_name, attachmentName) == 0) { + found = true; + _gameRef->unregisterObject(_attachmentsPre[i]); + _attachmentsPre.removeAt(i); + i--; + } + } + for (int i = 0; i < _attachmentsPost.getSize(); i++) { + if (_attachmentsPost[i]->_name && scumm_stricmp(_attachmentsPost[i]->_name, attachmentName) == 0) { + found = true; + _gameRef->unregisterObject(_attachmentsPost[i]); + _attachmentsPost.removeAt(i); + i--; + } + } + } + stack->pushBool(found); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetAttachment + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetAttachment") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + + CAdObject *ret = NULL; + if (val->isInt()) { + int index = val->getInt(); + int currIndex = 0; + for (int i = 0; i < _attachmentsPre.getSize(); i++) { + if (currIndex == index) ret = _attachmentsPre[i]; + currIndex++; + } + for (int i = 0; i < _attachmentsPost.getSize(); i++) { + if (currIndex == index) ret = _attachmentsPost[i]; + currIndex++; + } + } else { + const char *attachmentName = val->getString(); + for (int i = 0; i < _attachmentsPre.getSize(); i++) { + if (_attachmentsPre[i]->_name && scumm_stricmp(_attachmentsPre[i]->_name, attachmentName) == 0) { + ret = _attachmentsPre[i]; + break; + } + } + if (!ret) { + for (int i = 0; i < _attachmentsPost.getSize(); i++) { + if (_attachmentsPost[i]->_name && scumm_stricmp(_attachmentsPost[i]->_name, attachmentName) == 0) { + ret = _attachmentsPre[i]; + break; + } + } + } + } + + if (ret != NULL) stack->pushNative(ret, true); + else stack->pushNULL(); + + return STATUS_OK; + } + + else return CBObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdObject::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.getSize()); + 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.getSize() + _attachmentsPost.getSize()); + return _scValue; + } + + + else return CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdObject::scToString() { + return "[ad object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::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 CAdObject::getHeight() { + if (!_currentSprite) return 0; + else { + CBFrame *frame = _currentSprite->_frames[_currentSprite->_currentFrame]; + int ret = 0; + for (int i = 0; i < frame->_subframes.getSize(); i++) { + ret = MAX(ret, frame->_subframes[i]->_hotspotY); + } + + if (_zoomable) { + float zoom = ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY); + ret = (int)(ret * zoom / 100); + } + return ret; + } +} + + +////////////////////////////////////////////////////////////////////////// +void CAdObject::talk(const char *text, const char *sound, uint32 duration, const char *stances, TTextAlign Align) { + if (!_sentence) _sentence = new CAdSentence(_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 = ((CAdGame *)_gameRef)->findSpeechFile(key); + delete [] key; + + if (sound) deleteSound = true; + } + } + + // load sound and set duration appropriately + if (sound) { + CBSound *snd = new CBSound(_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 -= ((CAdGame *)_gameRef)->_scene->getOffsetLeft(); + y -= ((CAdGame *)_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 += ((CAdGame *)_gameRef)->_scene->getOffsetLeft(); + _sentence->_pos.y += ((CAdGame *)_gameRef)->_scene->getOffsetTop(); + } + + _sentence->_fixedPos = !_subtitlesModRelative; + + + _sentence->setupTalkFile(sound); + + _state = STATE_TALKING; + + if (deleteSound) delete [] sound; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::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 CAdObject::persist(CBPersistMgr *persistMgr) { + CBObject::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 CAdObject::updateSounds() { + if (_sentence && _sentence->_sound) + updateOneSound(_sentence->_sound); + + return CBObject::updateSounds(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::resetSoundPan() { + if (_sentence && _sentence->_sound) { + _sentence->_sound->setPan(0.0f); + } + return CBObject::resetSoundPan(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::getExtendedFlag(const char *flagName) { + if (!flagName) return false; + else if (strcmp(flagName, "usable") == 0) return true; + + else return CBObject::getExtendedFlag(flagName); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::saveAsText(CBDynBuffer *buffer, int indent) { + if (_blockRegion) _blockRegion->saveAsText(buffer, indent + 2, "BLOCKED_REGION"); + if (_wptGroup) _wptGroup->saveAsText(buffer, indent + 2); + + CBBase::saveAsText(buffer, indent + 2); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::updateBlockRegion() { + CAdGame *adGame = (CAdGame *)_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; +} + +////////////////////////////////////////////////////////////////////////// +CAdInventory *CAdObject::getInventory() { + if (!_inventory) { + _inventory = new CAdInventory(_gameRef); + ((CAdGame *)_gameRef)->registerInventory(_inventory); + } + return _inventory; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::afterMove() { + CAdRegion *newRegions[MAX_NUM_REGIONS]; + + ((CAdGame *)_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 CAdObject::invalidateCurrRegions() { + for (int i = 0; i < MAX_NUM_REGIONS; i++) _currentRegions[i] = NULL; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::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 = ((CAdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) + _relativeScale; + } else { + *scaleX = *scaleY = 100; + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::updateSpriteAttachments() { + for (int i = 0; i < _attachmentsPre.getSize(); i++) { + _attachmentsPre[i]->update(); + } + for (int i = 0; i < _attachmentsPost.getSize(); i++) { + _attachmentsPost[i]->update(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::displaySpriteAttachments(bool preDisplay) { + if (preDisplay) { + for (int i = 0; i < _attachmentsPre.getSize(); i++) { + displaySpriteAttachment(_attachmentsPre[i]); + } + } else { + for (int i = 0; i < _attachmentsPost.getSize(); i++) { + displaySpriteAttachment(_attachmentsPost[i]); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::displaySpriteAttachment(CAdObject *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; +} + +////////////////////////////////////////////////////////////////////////// +CPartEmitter *CAdObject::createParticleEmitter(bool followParent, int offsetX, int offsetY) { + _partFollowParent = followParent; + _partOffsetX = offsetX; + _partOffsetY = offsetY; + + if (!_partEmitter) { + _partEmitter = new CPartEmitter(_gameRef, this); + if (_partEmitter) { + _gameRef->registerObject(_partEmitter); + } + } + updatePartEmitter(); + return _partEmitter; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdObject::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 new file mode 100644 index 0000000000..dd123092a3 --- /dev/null +++ b/engines/wintermute/ad/ad_object.h @@ -0,0 +1,123 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/particles/part_emitter.h" + +namespace WinterMute { + +class CAdWaypointGroup; +class CAdRegion; +class CAdSentence; +class CBFont; +class CBRegion; +class CAdInventory; + +#define MAX_NUM_REGIONS 10 + +class CAdObject : public CBObject { +public: + CPartEmitter *_partEmitter; + virtual CPartEmitter *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; + CAdRegion *_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(CAdObject, CBObject) + virtual void talk(const char *text, const char *sound = NULL, uint32 duration = 0, const char *stances = NULL, TTextAlign align = TAL_CENTER); + virtual int getHeight(); + CAdSentence *_sentence; + bool SetFont(const char *filename); + virtual bool update(); + virtual bool display(); + bool _drawn; + bool _active; + virtual bool playAnim(const char *filename); + CBSprite *_animSprite; + CBSprite *_currentSprite; + TObjectState _state; + TObjectState _nextState; + TObjectType _type; + CAdObject(CBGame *inGame); + virtual ~CAdObject(); + CBFont *_font; + CBSprite *_tempSprite2; + CBRegion *_blockRegion; + CAdWaypointGroup *_wptGroup; + CBRegion *_currentBlockRegion; + CAdWaypointGroup *_currentWptGroup; + CAdInventory *getInventory(); + + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + virtual bool afterMove(); + CAdRegion *_currentRegions[MAX_NUM_REGIONS]; + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + + CBArray _attachmentsPre; + CBArray _attachmentsPost; + + bool updateSpriteAttachments(); + bool displaySpriteAttachments(bool preDisplay); + CAdObject *_registerAlias; +private: + bool displaySpriteAttachment(CAdObject *attachment); + CAdInventory *_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 new file mode 100644 index 0000000000..780912ce08 --- /dev/null +++ b/engines/wintermute/ad/ad_path.cpp @@ -0,0 +1,112 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/ad_path.h" +#include "engines/wintermute/base/base_point.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdPath, false) + +////////////////////////////////////////////////////////////////////////// +CAdPath::CAdPath(CBGame *inGame): CBBase(inGame) { + _currIndex = -1; + _ready = false; +} + + +////////////////////////////////////////////////////////////////////////// +CAdPath::~CAdPath() { + reset(); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdPath::reset() { + for (int i = 0; i < _points.getSize(); i++) + delete _points[i]; + + _points.removeAll(); + _currIndex = -1; + _ready = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBPoint *CAdPath::getFirst() { + if (_points.getSize() > 0) { + _currIndex = 0; + return _points[_currIndex]; + } else return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBPoint *CAdPath::getNext() { + _currIndex++; + if (_currIndex < _points.getSize()) return _points[_currIndex]; + else return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBPoint *CAdPath::getCurrent() { + if (_currIndex >= 0 && _currIndex < _points.getSize()) return _points[_currIndex]; + else return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CAdPath::addPoint(CBPoint *point) { + _points.add(point); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdPath::setReady(bool ready) { + bool orig = _ready; + _ready = ready; + + return orig; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdPath::persist(CBPersistMgr *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 new file mode 100644 index 0000000000..f27362bfd9 --- /dev/null +++ b/engines/wintermute/ad/ad_path.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_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 CBPoint; +class CAdPath : public CBBase { +public: + DECLARE_PERSISTENT(CAdPath, CBBase) + CBPoint *getCurrent(); + bool setReady(bool ready = true); + void addPoint(CBPoint *point); + CBPoint *getNext(); + CBPoint *getFirst(); + void reset(); + CAdPath(CBGame *inGame); + virtual ~CAdPath(); + CBArray _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 new file mode 100644 index 0000000000..d4b910a30f --- /dev/null +++ b/engines/wintermute/ad/ad_path_point.cpp @@ -0,0 +1,75 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/ad/ad_path_point.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdPathPoint, false) + +////////////////////////////////////////////////////////////////////////// +CAdPathPoint::CAdPathPoint() { + x = y = 0; + _distance = 0; + + _marked = false; + _origin = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdPathPoint::CAdPathPoint(int initX, int initY, int initDistance) { + x = initX; + y = initY; + _distance = initDistance; + + _marked = false; + _origin = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdPathPoint::~CAdPathPoint() { + _origin = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdPathPoint::persist(CBPersistMgr *persistMgr) { + + CBPoint::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 new file mode 100644 index 0000000000..2a58237bb9 --- /dev/null +++ b/engines/wintermute/ad/ad_path_point.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADPATHPOINT_H +#define WINTERMUTE_ADPATHPOINT_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base_point.h" + +namespace WinterMute { + +class CAdPathPoint : public CBPoint { +public: + DECLARE_PERSISTENT(CAdPathPoint, CBPoint) + CAdPathPoint(int initX, int initY, int initDistance); + CAdPathPoint(); + virtual ~CAdPathPoint(); + CAdPathPoint *_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 new file mode 100644 index 0000000000..ae65be5013 --- /dev/null +++ b/engines/wintermute/ad/ad_region.cpp @@ -0,0 +1,392 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CAdRegion, false) + +////////////////////////////////////////////////////////////////////////// +CAdRegion::CAdRegion(CBGame *inGame): CBRegion(inGame) { + _blocked = false; + _decoration = false; + _zoom = 0; + _alpha = 0xFFFFFFFF; +} + + +////////////////////////////////////////////////////////////////////////// +CAdRegion::~CAdRegion() { +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdRegion::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdRegion::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdRegion::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; + CBParser parser(_gameRef); + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_REGION) { + _gameRef->LOG(0, "'REGION' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + for (int i = 0; i < _points.getSize(); i++) delete _points[i]; + _points.removeAll(); + + 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 CBPoint(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 CAdRegion::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CBRegion::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdRegion::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(_name); + 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 CBRegion::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdRegion::scSetProperty(const char *name, CScValue *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 CBRegion::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdRegion::scToString() { + return "[ad region]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdRegion::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "REGION {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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"); + + int i; + for (i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + if (_scProp) _scProp->saveAsText(buffer, indent + 2); + + for (i = 0; i < _points.getSize(); i++) { + buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); + } + + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdRegion::persist(CBPersistMgr *persistMgr) { + CBRegion::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 new file mode 100644 index 0000000000..62c5fd6ba3 --- /dev/null +++ b/engines/wintermute/ad/ad_region.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADREGION_H +#define WINTERMUTE_ADREGION_H + +#include "engines/wintermute/base/base_region.h" + +namespace WinterMute { + +class CAdRegion : public CBRegion { +public: + DECLARE_PERSISTENT(CAdRegion, CBRegion) + uint32 _alpha; + float _zoom; + bool _blocked; + bool _decoration; + CAdRegion(CBGame *inGame); + virtual ~CAdRegion(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..b653fbd36a --- /dev/null +++ b/engines/wintermute/ad/ad_response.cpp @@ -0,0 +1,143 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CAdResponse, false) + +////////////////////////////////////////////////////////////////////////// +CAdResponse::CAdResponse(CBGame *inGame): CBObject(inGame) { + _text = NULL; + _textOrig = NULL; + _icon = _iconHover = _iconPressed = NULL; + _font = NULL; + _iD = 0; + _responseType = RESPONSE_ALWAYS; +} + + +////////////////////////////////////////////////////////////////////////// +CAdResponse::~CAdResponse() { + 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 CAdResponse::setText(const char *text) { + CBUtils::setString(&_text, text); + CBUtils::setString(&_textOrig, text); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponse::setIcon(const char *filename) { + delete _icon; + _icon = new CBSprite(_gameRef); + if (!_icon || DID_FAIL(_icon->loadFile(filename))) { + _gameRef->LOG(0, "CAdResponse::setIcon failed for file '%s'", filename); + delete _icon; + _icon = NULL; + return STATUS_FAILED; + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdResponse::setFont(const char *filename) { + if (_font) _gameRef->_fontStorage->removeFont(_font); + _font = _gameRef->_fontStorage->addFont(filename); + if (!_font) { + _gameRef->LOG(0, "CAdResponse::setFont failed for file '%s'", filename); + return STATUS_FAILED; + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdResponse::setIconHover(const char *filename) { + delete _iconHover; + _iconHover = new CBSprite(_gameRef); + if (!_iconHover || DID_FAIL(_iconHover->loadFile(filename))) { + _gameRef->LOG(0, "CAdResponse::setIconHover failed for file '%s'", filename); + delete _iconHover; + _iconHover = NULL; + return STATUS_FAILED; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponse::setIconPressed(const char *filename) { + delete _iconPressed; + _iconPressed = new CBSprite(_gameRef); + if (!_iconPressed || DID_FAIL(_iconPressed->loadFile(filename))) { + _gameRef->LOG(0, "CAdResponse::setIconPressed failed for file '%s'", filename); + delete _iconPressed; + _iconPressed = NULL; + return STATUS_FAILED; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponse::persist(CBPersistMgr *persistMgr) { + + CBObject::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 new file mode 100644 index 0000000000..da450b2229 --- /dev/null +++ b/engines/wintermute/ad/ad_response.h @@ -0,0 +1,61 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADRESPONSE_H +#define WINTERMUTE_ADRESPONSE_H + + +#include "engines/wintermute/base/base_object.h" +#include "engines/wintermute/ad/ad_types.h" + +namespace WinterMute { +class CBFont; +class CAdResponse : public CBObject { +public: + DECLARE_PERSISTENT(CAdResponse, CBObject) + 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; + CBSprite *_icon; + CBSprite *_iconHover; + CBSprite *_iconPressed; + CBFont *_font; + char *_text; + char *_textOrig; + CAdResponse(CBGame *inGame); + virtual ~CAdResponse(); + 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 new file mode 100644 index 0000000000..2499c9a732 --- /dev/null +++ b/engines/wintermute/ad/ad_response_box.cpp @@ -0,0 +1,647 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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 "common/str.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdResponseBox, false) + +////////////////////////////////////////////////////////////////////////// +CAdResponseBox::CAdResponseBox(CBGame *inGame): CBObject(inGame) { + _font = _fontHover = NULL; + + _window = NULL; + _shieldWindow = new CUIWindow(_gameRef); + + _horizontal = false; + CBPlatform::setRectEmpty(&_responseArea); + _scrollOffset = 0; + _spacing = 0; + + _waitingScript = NULL; + _lastResponseText = NULL; + _lastResponseTextOrig = NULL; + + _verticalAlign = VAL_BOTTOM; + _align = TAL_LEFT; +} + + +////////////////////////////////////////////////////////////////////////// +CAdResponseBox::~CAdResponseBox() { + + 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 CAdResponseBox::clearResponses() { + for (int i = 0; i < _responses.getSize(); i++) { + delete _responses[i]; + } + _responses.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdResponseBox::clearButtons() { + for (int i = 0; i < _respButtons.getSize(); i++) { + delete _respButtons[i]; + } + _respButtons.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseBox::invalidateButtons() { + for (int i = 0; i < _respButtons.getSize(); 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 CAdResponseBox::createButtons() { + clearButtons(); + + _scrollOffset = 0; + for (int i = 0; i < _responses.getSize(); i++) { + CUIButton *btn = new CUIButton(_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 CAdResponseBox::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdResponseBox::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdResponseBox::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; + CBParser parser(_gameRef); + + 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 CUIWindow(_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 CBSprite(_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 (int i = 0; i < _window->_widgets.getSize(); i++) { + if (!_window->_widgets[i]->_listenerObject) + _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseBox::saveAsText(CBDynBuffer *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->_filename) + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); + if (_fontHover && _fontHover->_filename) + buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->_filename); + + if (_cursor && _cursor->_filename) + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); + + 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("CAdResponseBox::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 + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseBox::display() { + Rect32 rect = _responseArea; + if (_window) { + CBPlatform::offsetRect(&rect, _window->_posX, _window->_posY); + //_window->display(); + } + + int xxx, yyy, i; + + xxx = rect.left; + yyy = rect.top; + + // shift down if needed + if (!_horizontal) { + int total_height = 0; + for (i = 0; i < _respButtons.getSize(); i++) total_height += (_respButtons[i]->_height + _spacing); + total_height -= _spacing; + + switch (_verticalAlign) { + case VAL_BOTTOM: + if (yyy + total_height < rect.bottom) + yyy = rect.bottom - total_height; + break; + + case VAL_CENTER: + if (yyy + total_height < rect.bottom) + yyy += ((rect.bottom - rect.top) - total_height) / 2; + break; + + case VAL_TOP: + // do nothing + break; + } + } + + // prepare response buttons + bool scrollNeeded = false; + for (i = _scrollOffset; i < _respButtons.getSize(); 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.getSize(); i++) { + _respButtons[i]->display(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseBox::listen(CBScriptHolder *param1, uint32 param2) { + CUIObject *obj = (CUIObject *)param1; + + switch (obj->_type) { + case UI_BUTTON: + if (scumm_stricmp(obj->_name, "prev") == 0) { + _scrollOffset--; + } else if (scumm_stricmp(obj->_name, "next") == 0) { + _scrollOffset++; + } else if (scumm_stricmp(obj->_name, "response") == 0) { + if (_waitingScript) _waitingScript->_stack->pushInt(_responses[param2]->_iD); + handleResponse(_responses[param2]); + _waitingScript = NULL; + _gameRef->_state = GAME_RUNNING; + ((CAdGame *)_gameRef)->_stateEx = GAME_NORMAL; + _ready = true; + invalidateButtons(); + clearResponses(); + } else return CBObject::listen(param1, param2); + break; + default: + error("AdResponseBox::Listen - Unhandled enum"); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseBox::persist(CBPersistMgr *persistMgr) { + CBObject::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 CAdResponseBox::weedResponses() { + CAdGame *adGame = (CAdGame *)_gameRef; + + for (int i = 0; i < _responses.getSize(); i++) { + switch (_responses[i]->_responseType) { + case RESPONSE_ONCE: + if (adGame->branchResponseUsed(_responses[i]->_iD)) { + delete _responses[i]; + _responses.removeAt(i); + i--; + } + break; + + case RESPONSE_ONCE_GAME: + if (adGame->gameResponseUsed(_responses[i]->_iD)) { + delete _responses[i]; + _responses.removeAt(i); + i--; + } + break; + default: + warning("CAdResponseBox::WeedResponses - Unhandled enum"); + break; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CAdResponseBox::setLastResponseText(const char *text, const char *textOrig) { + CBUtils::setString(&_lastResponseText, text); + CBUtils::setString(&_lastResponseTextOrig, textOrig); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseBox::handleResponse(CAdResponse *response) { + setLastResponseText(response->_text, response->_textOrig); + + CAdGame *adGame = (CAdGame *)_gameRef; + + switch (response->_responseType) { + case RESPONSE_ONCE: + adGame->addBranchResponse(response->_iD); + break; + + case RESPONSE_ONCE_GAME: + adGame->addGameResponse(response->_iD); + break; + default: + warning("CAdResponseBox::HandleResponse - Unhandled enum"); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBObject *CAdResponseBox::getNextAccessObject(CBObject *currObject) { + CBArray objects; + getObjects(objects, true); + + if (objects.getSize() == 0) return NULL; + else { + if (currObject != NULL) { + for (int i = 0; i < objects.getSize(); i++) { + if (objects[i] == currObject) { + if (i < objects.getSize() - 1) return objects[i + 1]; + else break; + } + } + } + return objects[0]; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +CBObject *CAdResponseBox::getPrevAccessObject(CBObject *currObject) { + CBArray objects; + getObjects(objects, true); + + if (objects.getSize() == 0) return NULL; + else { + if (currObject != NULL) { + for (int i = objects.getSize() - 1; i >= 0; i--) { + if (objects[i] == currObject) { + if (i > 0) return objects[i - 1]; + else break; + } + } + } + return objects[objects.getSize() - 1]; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseBox::getObjects(CBArray &objects, bool interactiveOnly) { + for (int i = 0; i < _respButtons.getSize(); 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 new file mode 100644 index 0000000000..7c611ef2d6 --- /dev/null +++ b/engines/wintermute/ad/ad_response_box.h @@ -0,0 +1,87 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADRESPONSEBOX_H +#define WINTERMUTE_ADRESPONSEBOX_H + + +#include "engines/wintermute/base/base_object.h" + +namespace WinterMute { + +class CUIButton; +class CUIWindow; +class CUIObject; +class CAdResponse; +class CAdResponseBox : public CBObject { +public: + CBObject *getNextAccessObject(CBObject *CurrObject); + CBObject *getPrevAccessObject(CBObject *CurrObject); + bool getObjects(CBArray &objects, bool interactiveOnly); + + bool handleResponse(CAdResponse *response); + void setLastResponseText(const char *text, const char *textOrig); + char *_lastResponseText; + char *_lastResponseTextOrig; + DECLARE_PERSISTENT(CAdResponseBox, CBObject) + CScScript *_waitingScript; + virtual bool listen(CBScriptHolder *param1, uint32 param2); + typedef enum { + EVENT_PREV, + EVENT_NEXT, + EVENT_RESPONSE + } TResponseEvent; + + bool weedResponses(); + bool display(); + int _spacing; + int _scrollOffset; + CBFont *_fontHover; + CBFont *_font; + bool createButtons(); + bool invalidateButtons(); + void clearButtons(); + void clearResponses(); + CAdResponseBox(CBGame *inGame); + virtual ~CAdResponseBox(); + CBArray _responses; + CBArray _respButtons; + CUIWindow *_window; + CUIWindow *_shieldWindow; + bool _horizontal; + Rect32 _responseArea; + int _verticalAlign; + TTextAlign _align; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *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 new file mode 100644 index 0000000000..02b819d6de --- /dev/null +++ b/engines/wintermute/ad/ad_response_context.cpp @@ -0,0 +1,70 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/ad_response_context.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdResponseContext, false) + +////////////////////////////////////////////////////////////////////////// +CAdResponseContext::CAdResponseContext(CBGame *inGame): CBBase(inGame) { + _iD = 0; + _context = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdResponseContext::~CAdResponseContext() { + delete[] _context; + _context = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdResponseContext::persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_gameRef)); + persistMgr->transfer(TMEMBER(_context)); + persistMgr->transfer(TMEMBER(_iD)); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CAdResponseContext::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 new file mode 100644 index 0000000000..79eaa27640 --- /dev/null +++ b/engines/wintermute/ad/ad_response_context.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADRESPONSECONTEXT_H +#define WINTERMUTE_ADRESPONSECONTEXT_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CAdResponseContext : public CBBase { +public: + void setContext(const char *context); + int _iD; + char *_context; + DECLARE_PERSISTENT(CAdResponseContext, CBBase) + CAdResponseContext(CBGame *inGame); + virtual ~CAdResponseContext(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/ad/ad_rot_level.cpp b/engines/wintermute/ad/ad_rot_level.cpp new file mode 100644 index 0000000000..0ffbaf6919 --- /dev/null +++ b/engines/wintermute/ad/ad_rot_level.cpp @@ -0,0 +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/dcgf.h" +#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(CAdRotLevel, false) + + +////////////////////////////////////////////////////////////////////////// +CAdRotLevel::CAdRotLevel(CBGame *inGame): CBObject(inGame) { + _posX = 0; + _rotation = 0.0f; +} + + +////////////////////////////////////////////////////////////////////////// +CAdRotLevel::~CAdRotLevel() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdRotLevel::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdRotLevel::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdRotLevel::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; + CBParser parser(_gameRef); + + 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 CAdRotLevel::saveAsText(CBDynBuffer *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); + CBBase::saveAsText(buffer, indent + 2); + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdRotLevel::persist(CBPersistMgr *persistMgr) { + + CBObject::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 new file mode 100644 index 0000000000..2bd9519d65 --- /dev/null +++ b/engines/wintermute/ad/ad_rot_level.h @@ -0,0 +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 CAdRotLevel : public CBObject { +public: + DECLARE_PERSISTENT(CAdRotLevel, CBObject) + CAdRotLevel(CBGame *inGame); + virtual ~CAdRotLevel(); + float _rotation; + virtual bool saveAsText(CBDynBuffer *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 new file mode 100644 index 0000000000..220d3c4b39 --- /dev/null +++ b/engines/wintermute/ad/ad_scale_level.cpp @@ -0,0 +1,157 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CAdScaleLevel, false) + +////////////////////////////////////////////////////////////////////////// +CAdScaleLevel::CAdScaleLevel(CBGame *inGame): CBObject(inGame) { + _posY = 0; + _scale = 100; +} + + +////////////////////////////////////////////////////////////////////////// +CAdScaleLevel::~CAdScaleLevel() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScaleLevel::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdScaleLevel::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdScaleLevel::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; + CBParser parser(_gameRef); + + 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 CAdScaleLevel::saveAsText(CBDynBuffer *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); + CBBase::saveAsText(buffer, indent + 2); + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScaleLevel::persist(CBPersistMgr *persistMgr) { + + CBObject::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 new file mode 100644 index 0000000000..4a81c00dda --- /dev/null +++ b/engines/wintermute/ad/ad_scale_level.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADSCALELEVEL_H +#define WINTERMUTE_ADSCALELEVEL_H + + +#include "engines/wintermute/base/base_object.h" + +namespace WinterMute { + +class CAdScaleLevel : public CBObject { +public: + DECLARE_PERSISTENT(CAdScaleLevel, CBObject) + float _scale; + CAdScaleLevel(CBGame *inGame); + virtual ~CAdScaleLevel(); + virtual bool saveAsText(CBDynBuffer *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 new file mode 100644 index 0000000000..11030d6996 --- /dev/null +++ b/engines/wintermute/ad/ad_scene.cpp @@ -0,0 +1,2752 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/platform_osystem.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 + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdScene, false) + +////////////////////////////////////////////////////////////////////////// +CAdScene::CAdScene(CBGame *inGame): CBObject(inGame) { + _pfTarget = new CBPoint; + setDefaults(); +} + + +////////////////////////////////////////////////////////////////////////// +CAdScene::~CAdScene() { + cleanup(); + _gameRef->unregisterObject(_fader); + delete _pfTarget; + _pfTarget = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CAdScene::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 CBFader(_gameRef); + _gameRef->registerObject(_fader); + + _viewport = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CAdScene::cleanup() { + CBObject::cleanup(); + + _mainLayer = NULL; // reference only + + int i; + + delete _shieldWindow; + _shieldWindow = NULL; + + _gameRef->unregisterObject(_fader); + _fader = NULL; + + for (i = 0; i < _layers.getSize(); i++) + _gameRef->unregisterObject(_layers[i]); + _layers.removeAll(); + + + for (i = 0; i < _waypointGroups.getSize(); i++) + _gameRef->unregisterObject(_waypointGroups[i]); + _waypointGroups.removeAll(); + + for (i = 0; i < _scaleLevels.getSize(); i++) + _gameRef->unregisterObject(_scaleLevels[i]); + _scaleLevels.removeAll(); + + for (i = 0; i < _rotLevels.getSize(); i++) + _gameRef->unregisterObject(_rotLevels[i]); + _rotLevels.removeAll(); + + + for (i = 0; i < _pfPath.getSize(); i++) + delete _pfPath[i]; + _pfPath.removeAll(); + _pfPointsNum = 0; + + for (i = 0; i < _objects.getSize(); i++) + _gameRef->unregisterObject(_objects[i]); + _objects.removeAll(); + + delete _viewport; + _viewport = NULL; + + setDefaults(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::getPath(CBPoint source, CBPoint target, CAdPath *path, CBObject *requester) { + if (!_pfReady) return false; + else { + _pfReady = false; + *_pfTarget = target; + _pfTargetPath = path; + _pfRequester = requester; + + _pfTargetPath->reset(); + _pfTargetPath->setReady(false); + + // prepare working path + int i; + pfPointsStart(); + + // first point + //_pfPath.add(new CAdPathPoint(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 CAdPathPoint(target.x, target.y, INT_MAX)); + pfPointsAdd(target.x, target.y, INT_MAX); + + // active waypoints + for (i = 0; i < _waypointGroups.getSize(); i++) { + if (_waypointGroups[i]->_active) { + pfAddWaypointGroup(_waypointGroups[i], requester); + } + } + + + // free waypoints + for (i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentWptGroup) { + pfAddWaypointGroup(_objects[i]->_currentWptGroup, requester); + } + } + CAdGame *adGame = (CAdGame *)_gameRef; + for (i = 0; i < adGame->_objects.getSize(); i++) { + if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentWptGroup) { + pfAddWaypointGroup(adGame->_objects[i]->_currentWptGroup, requester); + } + } + + return true; + } +} + + +////////////////////////////////////////////////////////////////////////// +void CAdScene::pfAddWaypointGroup(CAdWaypointGroup *wpt, CBObject *requester) { + if (!wpt->_active) return; + + for (int i = 0; i < wpt->_points.getSize(); i++) { + if (isBlockedAt(wpt->_points[i]->x, wpt->_points[i]->y, true, requester)) continue; + + //_pfPath.add(new CAdPathPoint(Wpt->_points[i]->x, Wpt->_points[i]->y, INT_MAX)); + pfPointsAdd(wpt->_points[i]->x, wpt->_points[i]->y, INT_MAX); + } +} + + +////////////////////////////////////////////////////////////////////////// +float CAdScene::getZoomAt(int x, int y) { + float ret = 100; + + bool found = false; + if (_mainLayer) { + for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) { + CAdSceneNode *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 CAdScene::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.getSize() - 1; i >= 0; i--) { + CAdSceneNode *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 CAdScene::isBlockedAt(int x, int y, bool checkFreeObjects, CBObject *requester) { + bool ret = true; + + + if (checkFreeObjects) { + for (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { + if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) return true; + } + } + CAdGame *adGame = (CAdGame *)_gameRef; + for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _mainLayer->_nodes.getSize(); i++) { + CAdSceneNode *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 CAdScene::isWalkableAt(int x, int y, bool checkFreeObjects, CBObject *requester) { + bool ret = false; + + if (checkFreeObjects) { + for (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { + if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) return false; + } + } + CAdGame *adGame = (CAdGame *)_gameRef; + for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _mainLayer->_nodes.getSize(); i++) { + CAdSceneNode *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 CAdScene::getPointsDist(CBPoint p1, CBPoint p2, CBObject *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) { + CBUtils::swap(&x1, &x2); + CBUtils::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) { + CBUtils::swap(&x1, &x2); + CBUtils::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 CAdScene::pathFinderStep() { + int i; + // get lowest unmarked + int lowestDist = INT_MAX; + CAdPathPoint *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.insertAt(0, new CBPoint(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 CAdScene::initLoop() { +#ifdef _DEBUGxxxx + int nu_steps = 0; + uint32 start = _gameRef->_currentTime; + while (!_pfReady && CBPlatform::getTime() - 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 && CBPlatform::getTime() - start <= _pfMaxTime) pathFinderStep(); +#endif + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdScene::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + delete[] _filename; + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, filename); + + if (DID_FAIL(ret = loadBuffer(buffer, true))) _gameRef->LOG(0, "Error parsing SCENE file '%s'", filename); + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdScene::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; + CBParser parser(_gameRef); + + 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: { + CAdLayer *layer = new CAdLayer(_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: { + CAdWaypointGroup *wpt = new CAdWaypointGroup(_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: { + CAdScaleLevel *sl = new CAdScaleLevel(_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: { + CAdRotLevel *rl = new CAdRotLevel(_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: { + CAdEntity *entity = new CAdEntity(_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 CBSprite(_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 CBViewport(_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.", _filename); + + + sortScaleLevels(); + sortRotLevels(); + + _initialized = true; + + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::traverseNodes(bool doUpdate) { + if (!_initialized) return STATUS_OK; + + int j, k; + CAdGame *adGame = (CAdGame *)_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 (j = 0; j < _layers.getSize(); j++) { + if (!_layers[j]->_active) continue; + + // make layer exclusive + if (!doUpdate) { + if (_layers[j]->_closeUp && !_gameRef->_editorMode) { + if (!_shieldWindow) _shieldWindow = new CUIWindow(_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 (k = 0; k < _layers[j]->_nodes.getSize(); k++) { + CAdSceneNode *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 CAdScene::display() { + return traverseNodes(false); +} + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::updateFreeObjects() { + CAdGame *adGame = (CAdGame *)_gameRef; + bool is3DSet; + + // *** update all active objects + is3DSet = false; + for (int i = 0; i < adGame->_objects.getSize(); i++) { + if (!adGame->_objects[i]->_active) continue; + + adGame->_objects[i]->update(); + adGame->_objects[i]->_drawn = false; + } + + + for (int i = 0; i < _objects.getSize(); 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 CAdScene::displayRegionContent(CAdRegion *region, bool display3DOnly) { + CAdGame *adGame = (CAdGame *)_gameRef; + CBArray objects; + CAdObject *obj; + + // global objects + for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 + qsort(objects.getData(), objects.getSize(), sizeof(CAdObject *), CAdScene::compareObjs); + + // display them + for (int i = 0; i < objects.getSize(); 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 (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_active && _objects[i]->_editorOnly) { + _objects[i]->display(); + _objects[i]->_drawn = true; + } + } + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +int CAdScene::compareObjs(const void *obj1, const void *obj2) { + CAdObject *object1 = *(CAdObject **)obj1; + CAdObject *object2 = *(CAdObject **)obj2; + + if (object1->_posY < object2->_posY) return -1; + else if (object1->_posY > object2->_posY) return 1; + else return 0; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::displayRegionContentOld(CAdRegion *region) { + CAdGame *adGame = (CAdGame *)_gameRef; + CAdObject *obj; + + // display all objects in region sorted by _posY + do { + obj = NULL; + int minY = INT_MAX; + + // global objects + for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_active && _objects[i]->_editorOnly) { + _objects[i]->display(); + _objects[i]->_drawn = true; + } + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::update() { + return traverseNodes(true); +} + +////////////////////////////////////////////////////////////////////////// +void CAdScene::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 CAdScene::scrollToObject(CBObject *object) { + if (object) scrollTo(object->_posX, object->_posY - object->getHeight() / 2); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdScene::skipToObject(CBObject *object) { + if (object) skipTo(object->_posX, object->_posY - object->getHeight() / 2); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdScene::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 CAdScene::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // LoadActor + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "LoadActor") == 0) { + stack->correctParams(1); + CAdActor *act = new CAdActor(_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); + CAdEntity *ent = new CAdEntity(_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); + CScValue *val = stack->pop(); + + CAdEntity *ent = new CAdEntity(_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); + CScValue *val = stack->pop(); + CAdObject *obj = (CAdObject *)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); + CScValue *val1 = stack->pop(); + CScValue *val2 = stack->pop(); + if (val1->isNative()) { + skipToObject((CBObject *)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); + CScValue *val1 = stack->pop(); + CScValue *val2 = stack->pop(); + if (val1->isNative()) { + scrollToObject((CBObject *)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); + CScValue *val = stack->pop(); + if (val->isInt()) { + int layer = val->getInt(); + if (layer < 0 || layer >= _layers.getSize()) stack->pushNULL(); + else stack->pushNative(_layers[layer], true); + } else { + const char *LayerName = val->getString(); + bool LayerFound = false; + for (int i = 0; i < _layers.getSize(); i++) { + if (scumm_stricmp(LayerName, _layers[i]->_name) == 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 >= _waypointGroups.getSize()) 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(); + + CBObject *node = getNodeByName(nodeName); + if (node) stack->pushNative((CBScriptable *)node, true); + else stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFreeNode + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetFreeNode") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + + CAdObject *ret = NULL; + if (val->isInt()) { + int index = val->getInt(); + if (index >= 0 && index < _objects.getSize()) ret = _objects[index]; + } else { + const char *nodeName = val->getString(); + for (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i] && _objects[i]->_name && scumm_stricmp(_objects[i]->_name, 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(); + CScValue *val = stack->pop(); + + bool includeDecors = false; + if (!val->isNULL()) includeDecors = val->getBool(); + + if (_mainLayer) { + for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) { + CAdSceneNode *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 CBViewport(_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); + CScValue *val = stack->pop(); + + CAdLayer *layer = new CAdLayer(_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(); + CScValue *val = stack->pop(); + + CAdLayer *layer = new CAdLayer(_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 <= _layers.getSize() - 1) _layers.insertAt(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); + CScValue *val = stack->pop(); + + CAdLayer *toDelete = NULL; + if (val->isNative()) { + CBScriptable *temp = val->getNative(); + for (int i = 0; i < _layers.getSize(); i++) { + if (_layers[i] == temp) { + toDelete = _layers[i]; + break; + } + } + } else { + int index = val->getInt(); + if (index >= 0 && index < _layers.getSize()) { + 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 (int i = 0; i < _layers.getSize(); i++) { + if (_layers[i] == toDelete) { + _layers.removeAt(i); + _gameRef->unregisterObject(toDelete); + break; + } + } + stack->pushBool(true); + return STATUS_OK; + } + + else return CBObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdScene::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.getSize()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumWaypointGroups (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumWaypointGroups") == 0) { + _scValue->setInt(_waypointGroups.getSize()); + 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.getSize()); + 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 CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdScene::scToString() { + return "[scene object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::addObject(CAdObject *object) { + _objects.add(object); + return _gameRef->registerObject(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::removeObject(CAdObject *object) { + for (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i] == object) { + _objects.removeAt(i); + return _gameRef->unregisterObject(object); + } + } + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::saveAsText(CBDynBuffer *buffer, int indent) { + int i; + + buffer->putTextIndent(indent, "SCENE {\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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 (i = 0; i < _scripts.getSize(); 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"); + + CBBase::saveAsText(buffer, indent + 2); + + // waypoints + buffer->putTextIndent(indent + 2, "; ----- waypoints\n"); + for (i = 0; i < _waypointGroups.getSize(); i++) _waypointGroups[i]->saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent + 2, "\n"); + + // layers + buffer->putTextIndent(indent + 2, "; ----- layers\n"); + for (i = 0; i < _layers.getSize(); i++) _layers[i]->saveAsText(buffer, indent + 2); + + // scale levels + buffer->putTextIndent(indent + 2, "; ----- scale levels\n"); + for (i = 0; i < _scaleLevels.getSize(); i++) _scaleLevels[i]->saveAsText(buffer, indent + 2); + + // rotation levels + buffer->putTextIndent(indent + 2, "; ----- rotation levels\n"); + for (i = 0; i < _rotLevels.getSize(); i++) _rotLevels[i]->saveAsText(buffer, indent + 2); + + + buffer->putTextIndent(indent + 2, "\n"); + + // free entities + buffer->putTextIndent(indent + 2, "; ----- free entities\n"); + for (i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_type == OBJECT_ENTITY) { + _objects[i]->saveAsText(buffer, indent + 2); + + } + } + + + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::sortScaleLevels() { + bool changed; + do { + changed = false; + for (int i = 0; i < _scaleLevels.getSize() - 1; i++) { + if (_scaleLevels[i]->_posY > _scaleLevels[i + 1]->_posY) { + CAdScaleLevel *sl = _scaleLevels[i]; + _scaleLevels[i] = _scaleLevels[i + 1]; + _scaleLevels[i + 1] = sl; + + changed = true; + } + } + + } while (changed); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::sortRotLevels() { + bool changed; + do { + changed = false; + for (int i = 0; i < _rotLevels.getSize() - 1; i++) { + if (_rotLevels[i]->_posX > _rotLevels[i + 1]->_posX) { + CAdRotLevel *rl = _rotLevels[i]; + _rotLevels[i] = _rotLevels[i + 1]; + _rotLevels[i + 1] = rl; + + changed = true; + } + } + + } while (changed); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +float CAdScene::getScaleAt(int Y) { + CAdScaleLevel *prev = NULL; + CAdScaleLevel *next = NULL; + + for (int i = 0; i < _scaleLevels.getSize(); i++) { + /* CAdScaleLevel *xxx = _scaleLevels[i];*/ + /* int j = _scaleLevels.getSize(); */ + 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 CAdScene::persist(CBPersistMgr *persistMgr) { + CBObject::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 CAdScene::afterLoad() { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, CBObject *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) { + /* + if (X1 > X2) + { + Swap(&X1, &X2); + Swap(&Y1, &Y2); + } + */ + + 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 { + /* + if (Y1 > Y2) { + Swap(&X1, &X2); + Swap(&Y1, &Y2); + } + */ + + 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 CAdScene::correctTargetPoint(int startX, int startY, int *argX, int *argY, bool checkFreeObjects, CBObject *requester) { + int x = *argX; + int y = *argY; + + if (isWalkableAt(x, y, checkFreeObjects, requester) || !_mainLayer) { + return STATUS_OK; + } + + // right + int length_right = 0; + bool found_right = false; + for (x = *argX, y = *argY; x < _mainLayer->_width; x++, length_right++) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x - 5, y, checkFreeObjects, requester)) { + found_right = true; + break; + } + } + + // left + int length_left = 0; + bool found_left = false; + for (x = *argX, y = *argY; x >= 0; x--, length_left--) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x + 5, y, checkFreeObjects, requester)) { + found_left = true; + break; + } + } + + // up + int length_up = 0; + bool found_up = false; + for (x = *argX, y = *argY; y >= 0; y--, length_up--) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y + 5, checkFreeObjects, requester)) { + found_up = true; + break; + } + } + + // down + int length_down = 0; + bool found_down = false; + for (x = *argX, y = *argY; y < _mainLayer->_height; y++, length_down++) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y - 5, checkFreeObjects, requester)) { + found_down = true; + break; + } + } + + if (!found_left && !found_right && !found_up && !found_down) { + return STATUS_OK; + } + + int OffsetX = INT_MAX, OffsetY = INT_MAX; + + if (found_left && found_right) { + if (abs(length_left) < abs(length_right)) OffsetX = length_left; + else OffsetX = length_right; + } else if (found_left) OffsetX = length_left; + else if (found_right) OffsetX = length_right; + + if (found_up && found_down) { + if (abs(length_up) < abs(length_down)) OffsetY = length_up; + else OffsetY = length_down; + } else if (found_up) OffsetY = length_up; + else if (found_down) OffsetY = length_down; + + 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 CAdScene::pfPointsStart() { + _pfPointsNum = 0; +} + + +////////////////////////////////////////////////////////////////////////// +void CAdScene::pfPointsAdd(int x, int y, int distance) { + if (_pfPointsNum >= _pfPath.getSize()) { + _pfPath.add(new CAdPathPoint(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 CAdScene::getViewportOffset(int *offsetX, int *offsetY) { + CAdGame *adGame = (CAdGame *)_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 CAdScene::getViewportSize(int *width, int *height) { + CAdGame *adGame = (CAdGame *)_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 CAdScene::getOffsetLeft() { + int viewportX; + getViewportOffset(&viewportX); + + return _offsetLeft - viewportX; +} + + +////////////////////////////////////////////////////////////////////////// +int CAdScene::getOffsetTop() { + int viewportY; + getViewportOffset(NULL, &viewportY); + + return _offsetTop - viewportY; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::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 CAdScene::setOffset(int offsetLeft, int offsetTop) { + _offsetLeft = offsetLeft; + _offsetTop = offsetTop; +} + + +////////////////////////////////////////////////////////////////////////// +CBObject *CAdScene::getNodeByName(const char *name) { + CBObject *ret = NULL; + + // dependent objects + for (int i = 0; i < _layers.getSize(); i++) { + CAdLayer *layer = _layers[i]; + for (int j = 0; j < layer->_nodes.getSize(); j++) { + CAdSceneNode *node = layer->_nodes[j]; + if ((node->_type == OBJECT_ENTITY && !scumm_stricmp(name, node->_entity->_name)) || + (node->_type == OBJECT_REGION && !scumm_stricmp(name, node->_region->_name))) { + 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 (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_type == OBJECT_ENTITY && !scumm_stricmp(name, _objects[i]->_name)) { + return _objects[i]; + } + } + + // waypoint groups + for (int i = 0; i < _waypointGroups.getSize(); i++) { + if (!scumm_stricmp(name, _waypointGroups[i]->_name)) { + return _waypointGroups[i]; + } + } + + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::saveState() { + return persistState(true); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::loadState() { + return persistState(false); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::persistState(bool saving) { + if (!_persistentState) return STATUS_OK; + + CAdGame *adGame = (CAdGame *)_gameRef; + CAdSceneState *state = adGame->getSceneState(_filename, saving); + if (!state) return STATUS_OK; + + CAdNodeState *nodeState; + + // dependent objects + for (int i = 0; i < _layers.getSize(); i++) { + CAdLayer *layer = _layers[i]; + for (int j = 0; j < layer->_nodes.getSize(); j++) { + CAdSceneNode *node = layer->_nodes[j]; + switch (node->_type) { + case OBJECT_ENTITY: + if (!node->_entity->_saveState) continue; + nodeState = state->getNodeState(node->_entity->_name, 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->_name, saving); + if (nodeState) { + if (saving) nodeState->_active = node->_region->_active; + else node->_region->_active = nodeState->_active; + } + break; + default: + warning("CAdScene::PersistState - unhandled enum"); + break; + } + } + } + + // free entities + for (int i = 0; i < _objects.getSize(); i++) { + if (!_objects[i]->_saveState) continue; + if (_objects[i]->_type == OBJECT_ENTITY) { + nodeState = state->getNodeState(_objects[i]->_name, saving); + if (nodeState) { + nodeState->transferEntity((CAdEntity *)_objects[i], _persistentStateSprites, saving); + //if(Saving) NodeState->_active = _objects[i]->_active; + //else _objects[i]->_active = NodeState->_active; + } + } + } + + // waypoint groups + for (int i = 0; i < _waypointGroups.getSize(); i++) { + nodeState = state->getNodeState(_waypointGroups[i]->_name, saving); + if (nodeState) { + if (saving) nodeState->_active = _waypointGroups[i]->_active; + else _waypointGroups[i]->_active = nodeState->_active; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +float CAdScene::getRotationAt(int x, int y) { + CAdRotLevel *prev = NULL; + CAdRotLevel *next = NULL; + + for (int i = 0; i < _rotLevels.getSize(); i++) { + /* CAdRotLevel *xxx = _rotLevels[i]; + int j = _rotLevels.getSize();*/ + 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 CAdScene::handleItemAssociations(const char *itemName, bool show) { + for (int i = 0; i < _layers.getSize(); i++) { + CAdLayer *layer = _layers[i]; + for (int j = 0; j < layer->_nodes.getSize(); j++) { + if (layer->_nodes[j]->_type == OBJECT_ENTITY) { + CAdEntity *ent = layer->_nodes[j]->_entity; + + if (ent->_item && strcmp(ent->_item, itemName) == 0) ent->_active = show; + } + } + } + + for (int i = 0; i < _objects.getSize(); i++) { + if (_objects[i]->_type == OBJECT_ENTITY) { + CAdEntity *ent = (CAdEntity *)_objects[i]; + if (ent->_item && strcmp(ent->_item, itemName) == 0) ent->_active = show; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::getRegionsAt(int x, int y, CAdRegion **regionList, int numRegions) { + int numUsed = 0; + if (_mainLayer) { + for (int i = _mainLayer->_nodes.getSize() - 1; i >= 0; i--) { + CAdSceneNode *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 CAdScene::restoreDeviceObjects() { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBObject *CAdScene::getNextAccessObject(CBObject *currObject) { + CBArray objects; + getSceneObjects(objects, true); + + if (objects.getSize() == 0) return NULL; + else { + if (currObject != NULL) { + for (int i = 0; i < objects.getSize(); i++) { + if (objects[i] == currObject) { + if (i < objects.getSize() - 1) return objects[i + 1]; + else break; + } + } + } + return objects[0]; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +CBObject *CAdScene::getPrevAccessObject(CBObject *currObject) { + CBArray objects; + getSceneObjects(objects, true); + + if (objects.getSize() == 0) return NULL; + else { + if (currObject != NULL) { + for (int i = objects.getSize() - 1; i >= 0; i--) { + if (objects[i] == currObject) { + if (i > 0) return objects[i - 1]; + else break; + } + } + } + return objects[objects.getSize() - 1]; + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::getSceneObjects(CBArray &objects, bool interactiveOnly) { + for (int i = 0; i < _layers.getSize(); i++) { + // close-up layer -> remove everything below it + if (interactiveOnly && _layers[i]->_closeUp) objects.removeAll(); + + + for (int j = 0; j < _layers[i]->_nodes.getSize(); j++) { + CAdSceneNode *node = _layers[i]->_nodes[j]; + switch (node->_type) { + case OBJECT_ENTITY: { + CAdEntity *ent = node->_entity; + if (ent->_active && (ent->_registrable || !interactiveOnly)) + objects.add(ent); + } + break; + + case OBJECT_REGION: { + CBArray regionObj; + getRegionObjects(node->_region, regionObj, interactiveOnly); + for (int newIndex = 0; newIndex < regionObj.getSize(); newIndex++) { + bool found = false; + for (int old = 0; old < objects.getSize(); old++) { + if (objects[old] == regionObj[newIndex]) { + found = true; + break; + } + } + if (!found) objects.add(regionObj[newIndex]); + } + //if(RegionObj.getSize() > 0) Objects.Append(RegionObj); + } + break; + default: + warning("CAdScene::GetSceneObjects - Unhandled enum"); + break; + } + } + } + + // objects outside any region + CBArray regionObj; + getRegionObjects(NULL, regionObj, interactiveOnly); + for (int newIndex = 0; newIndex < regionObj.getSize(); newIndex++) { + bool found = false; + for (int old = 0; old < objects.getSize(); old++) { + if (objects[old] == regionObj[newIndex]) { + found = true; + break; + } + } + if (!found) objects.add(regionObj[newIndex]); + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdScene::getRegionObjects(CAdRegion *region, CBArray &objects, bool interactiveOnly) { + CAdGame *adGame = (CAdGame *)_gameRef; + CAdObject *obj; + + // global objects + for (int i = 0; i < adGame->_objects.getSize(); 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 (int i = 0; i < _objects.getSize(); 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 + qsort(objects.getData(), objects.getSize(), sizeof(CAdObject *), CAdScene::compareObjs); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/ad/ad_scene.h b/engines/wintermute/ad/ad_scene.h new file mode 100644 index 0000000000..ab62a4a7fc --- /dev/null +++ b/engines/wintermute/ad/ad_scene.h @@ -0,0 +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 CUIWindow; +class CAdObject; +class CAdRegion; +class CBViewport; +class CAdLayer; +class CBPoint; +class CAdWaypointGroup; +class CAdPath; +class CAdScaleLevel; +class CAdRotLevel; +class CAdPathPoint; +class CAdScene : public CBObject { +public: + + CBObject *getNextAccessObject(CBObject *CurrObject); + CBObject *getPrevAccessObject(CBObject *CurrObject); + bool getSceneObjects(CBArray &Objects, bool InteractiveOnly); + bool getRegionObjects(CAdRegion *Region, CBArray &Objects, bool InteractiveOnly); + + bool afterLoad(); + + bool getRegionsAt(int X, int Y, CAdRegion **RegionList, int NumRegions); + bool handleItemAssociations(const char *ItemName, bool Show); + CUIWindow *_shieldWindow; + float getRotationAt(int X, int Y); + bool loadState(); + bool saveState(); + bool _persistentState; + bool _persistentStateSprites; + CBObject *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); + CBViewport *_viewport; + CBFader *_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, CBObject *Requester = NULL); + bool correctTargetPoint2(int StartX, int StartY, int *TargetX, int *TargetY, bool CheckFreeObjects, CBObject *Requester); + DECLARE_PERSISTENT(CAdScene, CBObject) + bool displayRegionContent(CAdRegion *Region = NULL, bool Display3DOnly = false); + bool displayRegionContentOld(CAdRegion *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(CBDynBuffer *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(CBObject *Object); + void scrollToObject(CBObject *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, CBObject *Requester = NULL); + bool isWalkableAt(int X, int Y, bool CheckFreeObjects = false, CBObject *Requester = NULL); + CAdLayer *_mainLayer; + float getZoomAt(int X, int Y); + bool getPath(CBPoint source, CBPoint target, CAdPath *path, CBObject *requester = NULL); + CAdScene(CBGame *inGame); + virtual ~CAdScene(); + CBArray _layers; + CBArray _objects; + CBArray _waypointGroups; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + int _width; + int _height; + bool addObject(CAdObject *Object); + bool removeObject(CAdObject *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; + CBArray _scaleLevels; + CBArray _rotLevels; + + virtual bool restoreDeviceObjects(); + int getPointsDist(CBPoint p1, CBPoint p2, CBObject *requester = NULL); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + + +private: + bool persistState(bool Saving = true); + void pfAddWaypointGroup(CAdWaypointGroup *Wpt, CBObject *Requester = NULL); + bool _pfReady; + CBPoint *_pfTarget; + CAdPath *_pfTargetPath; + CBObject *_pfRequester; + CBArray _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 new file mode 100644 index 0000000000..da7082105f --- /dev/null +++ b/engines/wintermute/ad/ad_scene_node.cpp @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/ad/ad_scene_node.h" +#include "engines/wintermute/base/base_game.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdSceneNode, false) + +////////////////////////////////////////////////////////////////////////// +CAdSceneNode::CAdSceneNode(CBGame *inGame): CBObject(inGame) { + _type = OBJECT_NONE; + _region = NULL; + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdSceneNode::~CAdSceneNode() { + _gameRef->unregisterObject(_region); + _region = NULL; + + _gameRef->unregisterObject(_entity); + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSceneNode::setEntity(CAdEntity *entity) { + _type = OBJECT_ENTITY; + _entity = entity; + return _gameRef->registerObject(entity); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSceneNode::setRegion(CAdRegion *region) { + _type = OBJECT_REGION; + _region = region; + return _gameRef->registerObject(region); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSceneNode::persist(CBPersistMgr *persistMgr) { + + CBObject::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 new file mode 100644 index 0000000000..1c25f91a2d --- /dev/null +++ b/engines/wintermute/ad/ad_scene_node.h @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_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 CAdSceneNode : public CBObject { +public: + DECLARE_PERSISTENT(CAdSceneNode, CBObject) + bool setRegion(CAdRegion *region); + bool setEntity(CAdEntity *entity); + CAdEntity *_entity; + CAdRegion *_region; + TObjectType _type; + CAdSceneNode(CBGame *inGame); + virtual ~CAdSceneNode(); + +}; + +} + +#endif diff --git a/engines/wintermute/ad/ad_scene_state.cpp b/engines/wintermute/ad/ad_scene_state.cpp new file mode 100644 index 0000000000..2ac36054a5 --- /dev/null +++ b/engines/wintermute/ad/ad_scene_state.cpp @@ -0,0 +1,88 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#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(CAdSceneState, false) + +////////////////////////////////////////////////////////////////////////// +CAdSceneState::CAdSceneState(CBGame *inGame): CBBase(inGame) { + _filename = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdSceneState::~CAdSceneState() { + delete[] _filename; + _filename = NULL; + + for (int i = 0; i < _nodeStates.getSize(); i++) delete _nodeStates[i]; + _nodeStates.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSceneState::persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_filename)); + _nodeStates.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CAdSceneState::setFilename(const char *filename) { + delete[] _filename; + _filename = new char [strlen(filename) + 1]; + if (_filename) strcpy(_filename, filename); +} + + +////////////////////////////////////////////////////////////////////////// +CAdNodeState *CAdSceneState::getNodeState(char *name, bool saving) { + for (int i = 0; i < _nodeStates.getSize(); i++) { + if (scumm_stricmp(_nodeStates[i]->_name, name) == 0) return _nodeStates[i]; + } + + if (saving) { + CAdNodeState *ret = new CAdNodeState(_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 new file mode 100644 index 0000000000..6df20e0578 --- /dev/null +++ b/engines/wintermute/ad/ad_scene_state.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_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 CAdNodeState; +class CAdSceneState : public CBBase { +public: + CAdNodeState *getNodeState(char *name, bool saving); + void setFilename(const char *filename); + DECLARE_PERSISTENT(CAdSceneState, CBBase) + CAdSceneState(CBGame *inGame); + virtual ~CAdSceneState(); + char *_filename; + CBArray _nodeStates; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/ad/ad_sentence.cpp b/engines/wintermute/ad/ad_sentence.cpp new file mode 100644 index 0000000000..2607993aa0 --- /dev/null +++ b/engines/wintermute/ad/ad_sentence.cpp @@ -0,0 +1,317 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CAdSentence, false) + +////////////////////////////////////////////////////////////////////////// +CAdSentence::CAdSentence(CBGame *inGame): CBBase(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; +} + + +////////////////////////////////////////////////////////////////////////// +CAdSentence::~CAdSentence() { + 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 CAdSentence::setText(const char *text) { + if (_text) delete [] _text; + _text = new char[strlen(text) + 1]; + if (_text) strcpy(_text, text); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdSentence::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 *CAdSentence::getCurrentStance() { + return getStance(_currentStance); +} + + +////////////////////////////////////////////////////////////////////////// +char *CAdSentence::getNextStance() { + _currentStance++; + return getStance(_currentStance); +} + + +////////////////////////////////////////////////////////////////////////// +char *CAdSentence::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) { + _tempStance[curr - start] = '\0'; + strncpy(_tempStance, start, curr - start); + } + + return _tempStance; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSentence::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 - ((CAdGame *)_gameRef)->_scene->getOffsetLeft(); + y = y - ((CAdGame *)_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 CAdSentence::setSound(CBSound *sound) { + if (!sound) return; + delete _sound; + _sound = sound; + _soundStarted = false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSentence::finish() { + if (_sound) _sound->stop(); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSentence::persist(CBPersistMgr *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 CAdSentence::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"); + + Common::SeekableReadStream *file = _gameRef->_fileManager->openFile(talkDefFileName.c_str()); + if (file) { + _gameRef->_fileManager->closeFile(file); + } else return STATUS_OK; // no talk def file found + + + _talkDef = new CAdTalkDef(_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 CAdSentence::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 (int i = 0; i < _talkDef->_nodes.getSize(); i++) { + if (_talkDef->_nodes[i]->isInTimeInterval(currentTime, dir)) { + talkNodeFound = true; + + CBSprite *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) { + CBSprite *newSprite = _talkDef->getDefaultSprite(dir); + if (newSprite) { + if (newSprite != _currentSprite) newSprite->reset(); + _currentSprite = newSprite; + } else _currentSprite = NULL; + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdSentence::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 new file mode 100644 index 0000000000..40f99ea830 --- /dev/null +++ b/engines/wintermute/ad/ad_sentence.h @@ -0,0 +1,85 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * 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 CAdTalkDef; +class CBFont; +class CBSprite; +class CBSound; +class CAdSentence : public CBBase { +public: + bool _freezable; + bool _fixedPos; + CBSprite *_currentSprite; + char *_currentSkelAnim; + bool update(TDirection dir = DI_DOWN); + bool setupTalkFile(const char *soundFilename); + DECLARE_PERSISTENT(CAdSentence, CBBase) + bool finish(); + void setSound(CBSound *Sound); + bool _soundStarted; + CBSound *_sound; + TTextAlign _align; + bool display(); + int _width; + Point32 _pos; + CBFont *_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; + CAdSentence(CBGame *inGame); + virtual ~CAdSentence(); + CAdTalkDef *_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 new file mode 100644 index 0000000000..f0925c6913 --- /dev/null +++ b/engines/wintermute/ad/ad_sprite_set.cpp @@ -0,0 +1,312 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdSpriteSet, false) + +////////////////////////////////////////////////////////////////////////// +CAdSpriteSet::CAdSpriteSet(CBGame *inGame, CBObject *owner): CBObject(inGame) { + _owner = owner; + + for (int i = 0; i < NUM_DIRECTIONS; i++) + _sprites[i] = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdSpriteSet::~CAdSpriteSet() { + for (int i = 0; i < NUM_DIRECTIONS; i++) { + delete _sprites[i]; + _sprites[i] = NULL; + } + + _owner = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdSpriteSet::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdSpriteSet::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 CAdSpriteSet::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; + CBParser parser(_gameRef); + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SPRITESET) { + _gameRef->LOG(0, "'SPRITESET' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + CBSprite *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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CAdSpriteSet::persist(CBPersistMgr *persistMgr) { + + CBObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_owner)); + for (int i = 0; i < NUM_DIRECTIONS; i++) { + persistMgr->transfer("", &_sprites[i]); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBSprite *CAdSpriteSet::getSprite(TDirection direction) { + int dir = (int)direction; + if (dir < 0) dir = 0; + if (dir >= NUM_DIRECTIONS) dir = NUM_DIRECTIONS - 1; + + CBSprite *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 CAdSpriteSet::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "SPRITESET {\n"); + if (_name) buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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]->_filename); + break; + case DI_UPRIGHT: + buffer->putTextIndent(indent + 2, "UP_RIGHT=\"%s\"\n", _sprites[i]->_filename); + break; + case DI_RIGHT: + buffer->putTextIndent(indent + 2, "RIGHT=\"%s\"\n", _sprites[i]->_filename); + break; + case DI_DOWNRIGHT: + buffer->putTextIndent(indent + 2, "DOWN_RIGHT=\"%s\"\n", _sprites[i]->_filename); + break; + case DI_DOWN: + buffer->putTextIndent(indent + 2, "DOWN=\"%s\"\n", _sprites[i]->_filename); + break; + case DI_DOWNLEFT: + buffer->putTextIndent(indent + 2, "DOWN_LEFT=\"%s\"\n", _sprites[i]->_filename); + break; + case DI_LEFT: + buffer->putTextIndent(indent + 2, "LEFT=\"%s\"\n", _sprites[i]->_filename); + break; + case DI_UPLEFT: + buffer->putTextIndent(indent + 2, "UP_LEFT=\"%s\"\n", _sprites[i]->_filename); + break; + } + } + } + + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CAdSpriteSet::containsSprite(CBSprite *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 new file mode 100644 index 0000000000..993832cfa3 --- /dev/null +++ b/engines/wintermute/ad/ad_sprite_set.h @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADSPRITESET_H +#define WINTERMUTE_ADSPRITESET_H + + +#include "engines/wintermute/base/base_object.h" +#include "engines/wintermute/base/base_sprite.h" // Added by ClassView + +namespace WinterMute { + +class CAdSpriteSet : public CBObject { +public: + bool containsSprite(CBSprite *sprite); + virtual bool saveAsText(CBDynBuffer *buffer, int indent = 0); + CBSprite *getSprite(TDirection direction); + DECLARE_PERSISTENT(CAdSpriteSet, CBObject) + CBObject *_owner; + CAdSpriteSet(CBGame *inGame, CBObject *owner = NULL); + virtual ~CAdSpriteSet(); + 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); + CBSprite *_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 new file mode 100644 index 0000000000..0cd62df603 --- /dev/null +++ b/engines/wintermute/ad/ad_talk_def.cpp @@ -0,0 +1,260 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CAdTalkDef, false) + +////////////////////////////////////////////////////////////////////////// +CAdTalkDef::CAdTalkDef(CBGame *inGame): CBObject(inGame) { + _defaultSpriteFilename = NULL; + _defaultSprite = NULL; + + _defaultSpriteSetFilename = NULL; + _defaultSpriteSet = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdTalkDef::~CAdTalkDef() { + for (int i = 0; i < _nodes.getSize(); i++) delete _nodes[i]; + _nodes.removeAll(); + + delete[] _defaultSpriteFilename; + delete _defaultSprite; + _defaultSpriteFilename = NULL; + _defaultSprite = NULL; + + delete[] _defaultSpriteSetFilename; + delete _defaultSpriteSet; + _defaultSpriteSetFilename = NULL; + _defaultSpriteSet = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkDef::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdTalkDef::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + CBUtils::setString(&_filename, 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 CAdTalkDef::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; + CBParser parser(_gameRef); + + 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: { + CAdTalkNode *Node = new CAdTalkNode(_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: + CBUtils::setString(&_defaultSpriteFilename, (char *)params); + break; + + case TOKEN_DEFAULT_SPRITESET_FILE: + CBUtils::setString(&_defaultSpriteSetFilename, (char *)params); + break; + + case TOKEN_DEFAULT_SPRITESET: { + delete _defaultSpriteSet; + _defaultSpriteSet = new CAdSpriteSet(_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 CBSprite(_gameRef); + if (!_defaultSprite || DID_FAIL(_defaultSprite->loadFile(_defaultSpriteFilename))) return STATUS_FAILED; + } + + if (_defaultSpriteSetFilename) { + _defaultSpriteSet = new CAdSpriteSet(_gameRef); + if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) return STATUS_FAILED; + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkDef::persist(CBPersistMgr *persistMgr) { + + CBObject::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 CAdTalkDef::saveAsText(CBDynBuffer *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 (int i = 0; i < _nodes.getSize(); i++) { + _nodes[i]->saveAsText(buffer, indent + 2); + buffer->putTextIndent(indent, "\n"); + } + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkDef::loadDefaultSprite() { + if (_defaultSpriteFilename && !_defaultSprite) { + _defaultSprite = new CBSprite(_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 CAdSpriteSet(_gameRef); + if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) { + delete _defaultSpriteSet; + _defaultSpriteSet = NULL; + return STATUS_FAILED; + } else return STATUS_OK; + } else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBSprite *CAdTalkDef::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 new file mode 100644 index 0000000000..0811f5b8f5 --- /dev/null +++ b/engines/wintermute/ad/ad_talk_def.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADTALKDEF_H +#define WINTERMUTE_ADTALKDEF_H + +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base_object.h" + +namespace WinterMute { +class CAdTalkNode; +class CAdSpriteSet; +class CAdTalkDef : public CBObject { +public: + char *_defaultSpriteSetFilename; + CAdSpriteSet *_defaultSpriteSet; + CBSprite *getDefaultSprite(TDirection Dir); + bool loadDefaultSprite(); + DECLARE_PERSISTENT(CAdTalkDef, CBObject) + + CAdTalkDef(CBGame *inGame); + virtual ~CAdTalkDef(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + CBArray _nodes; + char *_defaultSpriteFilename; + CBSprite *_defaultSprite; + virtual bool saveAsText(CBDynBuffer *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 new file mode 100644 index 0000000000..28e62798c2 --- /dev/null +++ b/engines/wintermute/ad/ad_talk_holder.cpp @@ -0,0 +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/dcgf.h" +#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/wintermute.h" +#include "common/str.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CAdTalkHolder, false) + +////////////////////////////////////////////////////////////////////////// +CAdTalkHolder::CAdTalkHolder(CBGame *inGame): CAdObject(inGame) { + _sprite = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CAdTalkHolder::~CAdTalkHolder() { + delete _sprite; + _sprite = NULL; + + for (int i = 0; i < _talkSprites.getSize(); i++) + delete _talkSprites[i]; + _talkSprites.removeAll(); + + for (int i = 0; i < _talkSpritesEx.getSize(); i++) + delete _talkSpritesEx[i]; + _talkSpritesEx.removeAll(); +} + +////////////////////////////////////////////////////////////////////////// +CBSprite *CAdTalkHolder::getTalkStance(const char *stance) { + CBSprite *ret = NULL; + + + // forced stance? + if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { + _forcedTalkAnimUsed = true; + delete _animSprite; + _animSprite = new CBSprite(_gameRef, this); + if (_animSprite) { + bool res = _animSprite->loadFile(_forcedTalkAnimName); + if (DID_FAIL(res)) { + _gameRef->LOG(res, "CAdTalkHolder::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", _name, _forcedTalkAnimName); + delete _animSprite; + _animSprite = NULL; + } else return _animSprite; + } + } + + + if (stance != NULL) { + // search special talk stances + for (int i = 0; i < _talkSpritesEx.getSize(); i++) { + if (scumm_stricmp(_talkSpritesEx[i]->_name, stance) == 0) { + ret = _talkSpritesEx[i]; + break; + } + } + if (ret == NULL) { + // serach generic talk stances + for (int i = 0; i < _talkSprites.getSize(); i++) { + if (scumm_stricmp(_talkSprites[i]->_name, stance) == 0) { + ret = _talkSprites[i]; + break; + } + } + } + } + + // not a valid stance? get a random one + if (ret == NULL) { + if (_talkSprites.getSize() < 1) ret = _sprite; + else { + // TODO: remember last + int rnd = g_wintermute->randInt(0, _talkSprites.getSize() - 1); + ret = _talkSprites[rnd]; + } + } + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CAdTalkHolder::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetSprite + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetSprite") == 0) { + stack->correctParams(1); + + CScValue *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(); + CBSprite *spr = new CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_sprite->_filename); + 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(); + + CBSprite *spr = new CBSprite(_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 (int i = 0; i < _talkSpritesEx.getSize(); i++) { + if (scumm_stricmp(_talkSpritesEx[i]->_filename, filename) == 0) { + if (_currentSprite == _talkSpritesEx[i]) + setCurrent = true; + if (_tempSprite2 == _talkSpritesEx[i]) + setTemp2 = true; + delete _talkSpritesEx[i]; + _talkSpritesEx.removeAt(i); + break; + } + } + } else { + for (int i = 0; i < _talkSprites.getSize(); i++) { + if (scumm_stricmp(_talkSprites[i]->_filename, filename) == 0) { + if (_currentSprite == _talkSprites[i]) + setCurrent = true; + if (_tempSprite2 == _talkSprites[i]) + setTemp2 = true; + delete _talkSprites[i]; + _talkSprites.removeAt(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; + + CBSprite *spr = new CBSprite(_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 (int i = 0; i < _talkSpritesEx.getSize(); i++) { + if (_talkSpritesEx[i] == _currentSprite) + setCurrent = true; + if (_talkSpritesEx[i] == _tempSprite2) + setTemp2 = true; + delete _talkSpritesEx[i]; + } + _talkSpritesEx.removeAll(); + } else { + for (int i = 0; i < _talkSprites.getSize(); i++) { + if (_talkSprites[i] == _currentSprite) setCurrent = true; + if (_talkSprites[i] == _tempSprite2) setTemp2 = true; + delete _talkSprites[i]; + } + _talkSprites.removeAll(); + } + + // 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 CAdObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdTalkHolder::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("talk-holder"); + return _scValue; + } + + else return CAdObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkHolder::scSetProperty(const char *name, CScValue *value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Item + ////////////////////////////////////////////////////////////////////////// + if(strcmp(name, "Item")==0){ + SetItem(value->getString()); + return STATUS_OK; + } + + else*/ return CAdObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CAdTalkHolder::scToString() { + return "[talk-holder object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkHolder::saveAsText(CBDynBuffer *buffer, int indent) { + for (int i = 0; i < _talkSprites.getSize(); i++) { + if (_talkSprites[i]->_filename) + buffer->putTextIndent(indent + 2, "TALK=\"%s\"\n", _talkSprites[i]->_filename); + } + + for (int i = 0; i < _talkSpritesEx.getSize(); i++) { + if (_talkSpritesEx[i]->_filename) + buffer->putTextIndent(indent + 2, "TALK_SPECIAL=\"%s\"\n", _talkSpritesEx[i]->_filename); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkHolder::persist(CBPersistMgr *persistMgr) { + CAdObject::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 new file mode 100644 index 0000000000..50c2f3504b --- /dev/null +++ b/engines/wintermute/ad/ad_talk_holder.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADTALKHOLDER_H +#define WINTERMUTE_ADTALKHOLDER_H + +#include "engines/wintermute/ad/ad_object.h" + +namespace WinterMute { + +class CAdTalkHolder : public CAdObject { +public: + DECLARE_PERSISTENT(CAdTalkHolder, CAdObject) + virtual CBSprite *getTalkStance(const char *stance); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + CBSprite *_sprite; + CBArray _talkSprites; + CBArray _talkSpritesEx; + CAdTalkHolder(CBGame *inGame); + virtual ~CAdTalkHolder(); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..3b82d731c9 --- /dev/null +++ b/engines/wintermute/ad/ad_talk_node.cpp @@ -0,0 +1,266 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CAdTalkNode, false) + +////////////////////////////////////////////////////////////////////////// +CAdTalkNode::CAdTalkNode(CBGame *inGame): CBBase(inGame) { + _sprite = NULL; + _spriteFilename = NULL; + _spriteSet = NULL; + _spriteSetFilename = NULL; + _comment = NULL; + + _startTime = _endTime = 0; + _playToEnd = false; + _preCache = false; +} + + +////////////////////////////////////////////////////////////////////////// +CAdTalkNode::~CAdTalkNode() { + 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 CAdTalkNode::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; + CBParser parser(_gameRef); + + 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: + CBUtils::setString(&_spriteFilename, (char *)params); + break; + + case TOKEN_SPRITESET_FILE: + CBUtils::setString(&_spriteSetFilename, (char *)params); + break; + + case TOKEN_SPRITESET: { + delete _spriteSet; + _spriteSet = new CAdSpriteSet(_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) CBUtils::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 CBSprite(_gameRef); + if (!_sprite || DID_FAIL(_sprite->loadFile(_spriteFilename))) + return STATUS_FAILED; + } + + if (_preCache && _spriteSetFilename) { + delete _spriteSet; + _spriteSet = new CAdSpriteSet(_gameRef); + if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) + return STATUS_FAILED; + } + + return STATUS_OK; +} + + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkNode::persist(CBPersistMgr *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 CAdTalkNode::saveAsText(CBDynBuffer *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"); + + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkNode::loadSprite() { + if (_spriteFilename && !_sprite) { + _sprite = new CBSprite(_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 CAdSpriteSet(_gameRef); + if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) { + delete _spriteSet; + _spriteSet = NULL; + return STATUS_FAILED; + } else return STATUS_OK; + } + + else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdTalkNode::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; +} + + +////////////////////////////////////////////////////////////////////////// +CBSprite *CAdTalkNode::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 new file mode 100644 index 0000000000..55adf88e83 --- /dev/null +++ b/engines/wintermute/ad/ad_talk_node.h @@ -0,0 +1,63 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADTALKNODE_H +#define WINTERMUTE_ADTALKNODE_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base.h" + +namespace WinterMute { +class CAdSpriteSet; +class CBSprite; +class CAdTalkNode : public CBBase { +public: + char *_spriteSetFilename; + CAdSpriteSet *_spriteSet; + CBSprite *getSprite(TDirection dir); + bool isInTimeInterval(uint32 time, TDirection dir); + bool loadSprite(); + DECLARE_PERSISTENT(CAdTalkNode, CBBase) + + CAdTalkNode(CBGame *inGame); + virtual ~CAdTalkNode(); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent = 0); + char *_spriteFilename; + CBSprite *_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 new file mode 100644 index 0000000000..b88d6fe259 --- /dev/null +++ b/engines/wintermute/ad/ad_types.h @@ -0,0 +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 // WINTERMUTE_ADTYPES_H diff --git a/engines/wintermute/ad/ad_waypoint_group.cpp b/engines/wintermute/ad/ad_waypoint_group.cpp new file mode 100644 index 0000000000..4a902266ac --- /dev/null +++ b/engines/wintermute/ad/ad_waypoint_group.cpp @@ -0,0 +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/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(CAdWaypointGroup, false) + +////////////////////////////////////////////////////////////////////////// +CAdWaypointGroup::CAdWaypointGroup(CBGame *inGame): CBObject(inGame) { + _active = true; + _editorSelectedPoint = -1; + _lastMimicScale = -1; + _lastMimicX = _lastMimicY = INT_MIN; +} + + +////////////////////////////////////////////////////////////////////////// +CAdWaypointGroup::~CAdWaypointGroup() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CAdWaypointGroup::cleanup() { + for (int i = 0; i < _points.getSize(); i++) + delete _points[i]; + _points.removeAll(); + _editorSelectedPoint = -1; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdWaypointGroup::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CAdWaypointGroup::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CAdWaypointGroup::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; + CBParser parser(_gameRef); + + 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 CBPoint(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 CAdWaypointGroup::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "WAYPOINTS {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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); + CBBase::saveAsText(buffer, indent + 2); + + for (int i = 0; i < _points.getSize(); i++) { + buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); + } + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdWaypointGroup::persist(CBPersistMgr *persistMgr) { + + CBObject::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; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CAdWaypointGroup::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 CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdWaypointGroup::scSetProperty(const char *name, CScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Active") == 0) { + _active = value->getBool(); + return STATUS_OK; + } + + else return CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +bool CAdWaypointGroup::mimic(CAdWaypointGroup *wpt, float scale, int argX, int argY) { + if (scale == _lastMimicScale && argX == _lastMimicX && argY == _lastMimicY) return STATUS_OK; + + cleanup(); + + for (int i = 0; i < wpt->_points.getSize(); 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 CBPoint(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 new file mode 100644 index 0000000000..2cece9e88b --- /dev/null +++ b/engines/wintermute/ad/ad_waypoint_group.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_ADWAYPOINTGROUP_H +#define WINTERMUTE_ADWAYPOINTGROUP_H + +#include "engines/wintermute/base/base_object.h" + +namespace WinterMute { +class CBPoint; +class CAdWaypointGroup : public CBObject { +public: + float _lastMimicScale; + int _lastMimicX; + int _lastMimicY; + void cleanup(); + bool mimic(CAdWaypointGroup *wpt, float scale = 100.0f, int x = 0, int y = 0); + DECLARE_PERSISTENT(CAdWaypointGroup, CBObject) + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + bool _active; + CAdWaypointGroup(CBGame *inGame); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual ~CAdWaypointGroup(); + CBArray _points; + int _editorSelectedPoint; + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/BActiveRect.cpp b/engines/wintermute/base/BActiveRect.cpp deleted file mode 100644 index 836a93ad9a..0000000000 --- a/engines/wintermute/base/BActiveRect.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BActiveRect.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -CBActiveRect::CBActiveRect(CBGame *inGame): CBBase(inGame) { - CBPlatform::setRectEmpty(&_rect); - _owner = NULL; - _frame = NULL; - _region = NULL; - _zoomX = 100; - _zoomY = 100; - _offsetX = _offsetY = 0; - clipRect(); -} - - -////////////////////////////////////////////////////////////////////// -CBActiveRect::CBActiveRect(CBGame *inGame, CBObject *owner, CBSubFrame *frame, int x, int y, int width, int height, float zoomX, float zoomY, bool precise): CBBase(inGame) { - _owner = owner; - _frame = frame; - CBPlatform::setRect(&_rect, x, y, x + width, y + height); - _zoomX = zoomX; - _zoomY = zoomY; - _precise = precise; - _region = NULL; - _offsetX = _offsetY = 0; - clipRect(); -} - -////////////////////////////////////////////////////////////////////// -CBActiveRect::CBActiveRect(CBGame *inGame, CBObject *owner, CBRegion *region, int offsetX, int offsetY): CBBase(inGame) { - _owner = owner; - _region = region; - CBPlatform::copyRect(&_rect, ®ion->_rect); - CBPlatform::offsetRect(&_rect, -offsetX, -offsetY); - _zoomX = 100; - _zoomY = 100; - _precise = true; - _frame = NULL; - clipRect(); - _offsetX = offsetX; - _offsetY = offsetY; -} - - -////////////////////////////////////////////////////////////////////// -CBActiveRect::~CBActiveRect() { - _owner = NULL; - _frame = NULL; - _region = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void CBActiveRect::clipRect() { - Rect32 rc; - bool customViewport; - _gameRef->getCurrentViewportRect(&rc, &customViewport); - CBRenderer *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; - - CBPlatform::intersectRect(&_rect, &_rect, &rc); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BActiveRect.h b/engines/wintermute/base/BActiveRect.h deleted file mode 100644 index 935b91eaeb..0000000000 --- a/engines/wintermute/base/BActiveRect.h +++ /dev/null @@ -1,60 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BACTIVERECT_H -#define WINTERMUTE_BACTIVERECT_H - -#include "engines/wintermute/math/Rect32.h" -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { -class CBRegion; -class CBSubFrame; -class CBObject; -class CBActiveRect: CBBase { -public: - void clipRect(); - bool _precise; - float _zoomX; - float _zoomY; - CBSubFrame *_frame; - CBObject *_owner; - CBRegion *_region; - int _offsetX; - int _offsetY; - Rect32 _rect; - CBActiveRect(CBGame *inGameOwner = NULL); - CBActiveRect(CBGame *inGameOwner, CBObject *owner, CBSubFrame *frame, int x, int y, int width, int height, float zoomX = 100, float zoomY = 100, bool precise = true); - CBActiveRect(CBGame *inGame, CBObject *owner, CBRegion *region, int offsetX, int offsetY); - virtual ~CBActiveRect(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BBase.cpp b/engines/wintermute/base/BBase.cpp deleted file mode 100644 index 76e1150925..0000000000 --- a/engines/wintermute/base/BBase.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BBase.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -CBBase::CBBase(CBGame *gameOwner) { - _gameRef = gameOwner; - _persistable = true; -} - - -////////////////////////////////////////////////////////////////////////// -CBBase::CBBase() { - _gameRef = NULL; - _persistable = true; -} - - -////////////////////////////////////////////////////////////////////// -CBBase::~CBBase() { - _editorProps.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBBase::getEditorProp(const char *propName, const char *initVal) { - _editorPropsIter = _editorProps.find(propName); - if (_editorPropsIter != _editorProps.end()) - return _editorPropsIter->_value.c_str(); - //return _editorPropsIter->second.c_str(); // <- TODO Clean - else return initVal; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBBase::setEditorProp(const char *propName, const char *propValue) { - if (propName == NULL) return STATUS_FAILED; - - if (propValue == NULL) { - _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 CBBase::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; - CBParser parser(_gameRef); - - 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 CBBase::saveAsText(CBDynBuffer *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 + 2, "NAME=\"%s\"\n", (char *)_editorPropsIter->first.c_str()); // <- TODO, remove - //buffer->putTextIndent(indent + 2, "VALUE=\"%s\"\n", _editorPropsIter->second.c_str()); // <- TODO, remove - buffer->putTextIndent(indent, "}\n\n"); - - _editorPropsIter++; - } - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BBase.h b/engines/wintermute/base/BBase.h deleted file mode 100644 index e8c87f1f9e..0000000000 --- a/engines/wintermute/base/BBase.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BBASE_H -#define WINTERMUTE_BBASE_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 CBGame; -class CBDynBuffer; - -class CBBase { -public: - bool _persistable; - bool setEditorProp(const char *propName, const char *propValue); - const char *getEditorProp(const char *propName, const char *initVal = NULL); - CBBase(TDynamicConstructor, TDynamicConstructor) {}; - bool parseEditorProperty(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent = 0); - CBBase(); - CBGame *_gameRef; - CBBase(CBGame *GameOwner); - virtual ~CBBase(); - - Common::HashMap _editorProps; - Common::HashMap::iterator _editorPropsIter; - /* std::map _editorProps; - std::map::iterator _editorPropsIter;*/ -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BDebugger.cpp b/engines/wintermute/base/BDebugger.cpp deleted file mode 100644 index 92f282b6d1..0000000000 --- a/engines/wintermute/base/BDebugger.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BDebugger.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBDebugger::CBDebugger(CBGame *inGame) : CBBase(inGame) { - _enabled = false; -} - -////////////////////////////////////////////////////////////////////////// -CBDebugger::~CBDebugger(void) { -} - - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::initialize() { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::shutdown() { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onGameInit() { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onGameShutdown() { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onGameTick() { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onLog(unsigned int errorCode, const char *text) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptInit(CScScript *script) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptEventThreadInit(CScScript *script, CScScript *parentScript, const char *name) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptMethodThreadInit(CScScript *script, CScScript *parentScript, const char *name) { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptShutdown(CScScript *script) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptChangeLine(CScScript *script, int Line) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptChangeScope(CScScript *script, CScValue *scope) { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptShutdownScope(CScScript *script, CScValue *scope) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onVariableInit(EWmeDebuggerVariableType type, CScScript *script, CScValue *scope, CScValue *var, const char *variableName) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onVariableChangeValue(CScValue *var, CScValue *value) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::onScriptHitBreakpoint(CScScript *script) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -// IWmeDebugServer interface implementation -bool CBDebugger::attachClient(IWmeDebugClient *client) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::detachClient(IWmeDebugClient *client) { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::queryData(IWmeDebugClient *client) { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -int CBDebugger::getPropInt(const char *propName) { - return 0; -} - -////////////////////////////////////////////////////////////////////////// -double CBDebugger::getPropFloat(const char *propName) { - return 0.0; -} - -////////////////////////////////////////////////////////////////////////// -const char *CBDebugger::getPropString(const char *propName) { - return ""; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::getPropBool(const char *propName) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::setProp(const char *propName, int propValue) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::setProp(const char *propName, double propValue) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::setProp(const char *propName, const char *propValue) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::setProp(const char *propName, bool propValue) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::resolveFilename(const char *relativeFilename, char *absFilenameBuf, int absBufSize) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::addBreakpoint(const char *scriptFilename, int line) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::removeBreakpoint(const char *scriptFilename, int line) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBDebugger::continueExecution() { - return false; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BDebugger.h b/engines/wintermute/base/BDebugger.h deleted file mode 100644 index cea432f7a8..0000000000 --- a/engines/wintermute/base/BDebugger.h +++ /dev/null @@ -1,95 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BDEBUGGER_H -#define WINTERMUTE_BDEBUGGER_H - - -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/wme_debugger.h" - -// TODO: The entire debugger should possibly be removed - -namespace WinterMute { -class CScScript; -class CScValue; -class CBDebugger : public CBBase, public IWmeDebugServer { -public: - CBDebugger(CBGame *inGame); - virtual ~CBDebugger(void); - - // initialization - bool _enabled; - bool initialize(); - bool shutdown(); - - // internal interface - bool onGameInit(); - bool onGameShutdown(); - bool onGameTick(); - bool onLog(unsigned int errorCode, const char *text); - bool onScriptInit(CScScript *script); - bool onScriptEventThreadInit(CScScript *script, CScScript *parentScript, const char *name); - bool onScriptMethodThreadInit(CScScript *script, CScScript *parentScript, const char *name); - - bool onScriptShutdown(CScScript *script); - bool onScriptChangeLine(CScScript *script, int line); - bool onScriptChangeScope(CScScript *script, CScValue *scope); - bool onScriptShutdownScope(CScScript *script, CScValue *scope); - bool onVariableInit(EWmeDebuggerVariableType type, CScScript *script, CScValue *scope, CScValue *var, const char *variableName); - bool onVariableChangeValue(CScValue *var, CScValue *value); - - bool onScriptHitBreakpoint(CScScript *script); - - // IWmeDebugServer interface - virtual bool attachClient(IWmeDebugClient *client); - virtual bool detachClient(IWmeDebugClient *client); - virtual bool queryData(IWmeDebugClient *client); - - virtual int getPropInt(const char *propName); - virtual double getPropFloat(const char *propName); - virtual const char *getPropString(const char *propName); - virtual bool getPropBool(const char *propName); - - virtual bool setProp(const char *propName, int propValue); - virtual bool setProp(const char *propName, double propValue); - virtual bool setProp(const char *propName, const char *propValue); - virtual bool setProp(const char *propName, bool propValue); - - virtual bool resolveFilename(const char *relativeFilename, char *absFilenameBuf, int absBufSize); - - virtual bool addBreakpoint(const char *scriptFilename, int line); - virtual bool removeBreakpoint(const char *scriptFilename, int line); - - virtual bool continueExecution(); -private: -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BDynBuffer.cpp b/engines/wintermute/base/BDynBuffer.cpp deleted file mode 100644 index 9a2e071287..0000000000 --- a/engines/wintermute/base/BDynBuffer.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/base/BDynBuffer.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBDynBuffer::CBDynBuffer(CBGame *inGame, uint32 initSize, uint32 growBy): CBBase(inGame) { - _buffer = NULL; - _size = 0; - _realSize = 0; - - _offset = 0; - _initSize = initSize; - _growBy = growBy; - - _initialized = false; -} - - -////////////////////////////////////////////////////////////////////////// -CBDynBuffer::~CBDynBuffer() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void CBDynBuffer::cleanup() { - if (_buffer) free(_buffer); - _buffer = NULL; - _size = 0; - _realSize = 0; - _offset = 0; - _initialized = false; -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CBDynBuffer::getSize() { - return _size; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBDynBuffer::init(uint32 initSize) { - cleanup(); - - if (initSize == 0) initSize = _initSize; - - _buffer = (byte *)malloc(initSize); - if (!_buffer) { - _gameRef->LOG(0, "CBDynBuffer::Init - Error allocating %d bytes", initSize); - return STATUS_FAILED; - } - - _realSize = initSize; - _initialized = true; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBDynBuffer::putBytes(byte *buffer, uint32 size) { - if (!_initialized) init(); - - while (_offset + size > _realSize) { - _realSize += _growBy; - _buffer = (byte *)realloc(_buffer, _realSize); - if (!_buffer) { - _gameRef->LOG(0, "CBDynBuffer::PutBytes - Error reallocating buffer to %d bytes", _realSize); - return STATUS_FAILED; - } - } - - memcpy(_buffer + _offset, buffer, size); - _offset += size; - _size += size; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBDynBuffer::getBytes(byte *buffer, uint32 size) { - if (!_initialized) init(); - - if (_offset + size > _size) { - _gameRef->LOG(0, "CBDynBuffer::GetBytes - Buffer underflow"); - return STATUS_FAILED; - } - - memcpy(buffer, _buffer + _offset, size); - _offset += size; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CBDynBuffer::putDWORD(uint32 val) { - putBytes((byte *)&val, sizeof(uint32)); -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CBDynBuffer::getDWORD() { - uint32 ret; - getBytes((byte *)&ret, sizeof(uint32)); - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -void CBDynBuffer::putString(const char *val) { - if (!val) putString("(null)"); - else { - putDWORD(strlen(val) + 1); - putBytes((byte *)val, strlen(val) + 1); - } -} - - -////////////////////////////////////////////////////////////////////////// -char *CBDynBuffer::getString() { - uint32 len = getDWORD(); - char *ret = (char *)(_buffer + _offset); - _offset += len; - - if (!strcmp(ret, "(null)")) return NULL; - else return ret; -} - - -////////////////////////////////////////////////////////////////////////// -void CBDynBuffer::putText(const char *fmt, ...) { - va_list va; - - va_start(va, fmt); - putTextForm(fmt, va); - va_end(va); - -} - - -////////////////////////////////////////////////////////////////////////// -void CBDynBuffer::putTextIndent(int indent, const char *fmt, ...) { - va_list va; - - putText("%*s", indent, ""); - - va_start(va, fmt); - putTextForm(fmt, va); - va_end(va); -} - - -////////////////////////////////////////////////////////////////////////// -void CBDynBuffer::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/BDynBuffer.h b/engines/wintermute/base/BDynBuffer.h deleted file mode 100644 index 66e8182c68..0000000000 --- a/engines/wintermute/base/BDynBuffer.h +++ /dev/null @@ -1,66 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BDYNBUFFER_H -#define WINTERMUTE_BDYNBUFFER_H - - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBDynBuffer : public CBBase { -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(byte *buffer, uint32 size); - uint32 getSize(); - bool init(uint32 initSize = 0); - void cleanup(); - uint32 _size; - byte *_buffer; - CBDynBuffer(CBGame *inGame, uint32 initSize = 1000, uint32 growBy = 1000); - virtual ~CBDynBuffer(); - -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/BFader.cpp b/engines/wintermute/base/BFader.cpp deleted file mode 100644 index 9dec5e1e12..0000000000 --- a/engines/wintermute/base/BFader.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFader.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/util.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CBFader, false) - -////////////////////////////////////////////////////////////////////////// -CBFader::CBFader(CBGame *inGame): CBObject(inGame) { - _active = false; - _red = _green = _blue = 0; - _currentAlpha = 0x00; - _sourceAlpha = 0; - _targetAlpha = 0; - _duration = 1000; - _startTime = 0; - _system = false; -} - - -////////////////////////////////////////////////////////////////////////// -CBFader::~CBFader() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFader::update() { - if (!_active) return STATUS_OK; - - int alphaDelta = _targetAlpha - _sourceAlpha; - - uint32 time; - - if (_system) time = CBPlatform::getTime() - _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 CBFader::display() { - if (!_active) return STATUS_OK; - - if (_currentAlpha > 0x00) return _gameRef->_renderer->fadeToColor(BYTETORGBA(_red, _green, _blue, _currentAlpha)); - else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFader::deactivate() { - _active = false; - _ready = true; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFader::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 = CBPlatform::getTime(); - else _startTime = _gameRef->_timer; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFader::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 = CBPlatform::getTime(); - else _startTime = _gameRef->_timer; - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CBFader::getCurrentColor() { - return BYTETORGBA(_red, _green, _blue, _currentAlpha); -} - - - -////////////////////////////////////////////////////////////////////////// -bool CBFader::persist(CBPersistMgr *persistMgr) { - CBObject::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->_saving) _startTime = 0; - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BFader.h b/engines/wintermute/base/BFader.h deleted file mode 100644 index cc90d4603d..0000000000 --- a/engines/wintermute/base/BFader.h +++ /dev/null @@ -1,62 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFADER_H -#define WINTERMUTE_BFADER_H - - -#include "engines/wintermute/base/BObject.h" - -namespace WinterMute { - -class CBFader : public CBObject { -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(CBFader, CBObject) - CBFader(CBGame *inGame); - virtual ~CBFader(); - 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/BFileManager.cpp b/engines/wintermute/base/BFileManager.cpp deleted file mode 100644 index 34638f55e8..0000000000 --- a/engines/wintermute/base/BFileManager.cpp +++ /dev/null @@ -1,737 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFileManager.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/base/file/BDiskFile.h" -#include "engines/wintermute/base/file/BSaveThumbFile.h" -#include "engines/wintermute/base/file/BFileEntry.h" -#include "engines/wintermute/base/file/BPackage.h" -#include "engines/wintermute/base/file/BPkgFile.h" -#include "engines/wintermute/base/BResources.h" -#include "engines/wintermute/base/BRegistry.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/dcpackage.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/wintermute.h" -#include "common/str.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" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////// -CBFileManager::CBFileManager(CBGame *inGame): CBBase(inGame) { - _basePath = NULL; - - initPaths(); - registerPackages(); -} - - -////////////////////////////////////////////////////////////////////// -CBFileManager::~CBFileManager() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::cleanup() { - // delete registered paths - for (uint32 i = 0; i < _singlePaths.size(); i++) - delete [] _singlePaths[i]; - _singlePaths.clear(); - - for (uint32 i = 0; i < _packagePaths.size(); i++) - delete [] _packagePaths[i]; - _packagePaths.clear(); - - - // delete file entries - _filesIter = _files.begin(); - while (_filesIter != _files.end()) { - delete _filesIter->_value; - _filesIter++; - } - _files.clear(); - - // close open files - for (uint32 i = 0; i < _openFiles.size(); i++) { - delete _openFiles[i]; - } - _openFiles.clear(); - - - // delete packages - for (uint32 i = 0; i < _packages.size(); i++) - delete _packages[i]; - _packages.clear(); - - delete[] _basePath; - _basePath = NULL; - - return STATUS_OK; -} - - - -#define MAX_FILE_SIZE 10000000 -////////////////////////////////////////////////////////////////////// -byte *CBFileManager::readWholeFile(const Common::String &filename, uint32 *size, bool mustExist) { - byte *buffer = NULL; - - Common::SeekableReadStream *file = openFile(filename); - if (!file) { - if (mustExist) _gameRef->LOG(0, "Error opening file '%s'", filename.c_str()); - return NULL; - } - - /* - if (File->GetSize() > MAX_FILE_SIZE) { - _gameRef->LOG(0, "File '%s' exceeds the maximum size limit (%d bytes)", Filename, MAX_FILE_SIZE); - CloseFile(File); - return NULL; - } - */ - - - buffer = new byte[file->size() + 1]; - if (buffer == NULL) { - _gameRef->LOG(0, "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()) { - _gameRef->LOG(0, "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; -} - -Common::SeekableReadStream *CBFileManager::loadSaveGame(const Common::String &filename) { - Common::SaveFileManager *saveMan = g_wintermute->getSaveFileMan(); - Common::InSaveFile *file = saveMan->openForLoading(filename); - return file; -} - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::saveFile(const Common::String &filename, byte *buffer, uint32 bufferSize, bool compressed, byte *prefixBuffer, uint32 prefixSize) { - // TODO - warning("Implement SaveFile"); - - Common::SaveFileManager *saveMan = g_wintermute->getSaveFileMan(); - Common::OutSaveFile *file = saveMan->openForSaving(filename); - file->write(prefixBuffer, prefixSize); - file->write(buffer, bufferSize); - file->finalize(); - delete file; -#if 0 - RestoreCurrentDir(); - - CBUtils::CreatePath(filename, false); - - FILE *f = fopen(filename, "wb"); - if (!f) { - _gameRef->LOG(0, "Error opening file '%s' for writing.", filename); - return STATUS_FAILED; - } - - if (PrefixBuffer && PrefixSize) { - fwrite(PrefixBuffer, PrefixSize, 1, f); - } - - if (Compressed) { - uint32 CompSize = BufferSize + (BufferSize / 100) + 12; // 1% extra space - byte *CompBuffer = new byte[CompSize]; - if (!CompBuffer) { - _gameRef->LOG(0, "Error allocating compression buffer while saving '%s'", filename); - Compressed = false; - } else { - if (compress(CompBuffer, (uLongf *)&CompSize, Buffer, BufferSize) == Z_OK) { - uint32 magic = DCGF_MAGIC; - fwrite(&magic, sizeof(uint32), 1, f); - magic = COMPRESSED_FILE_MAGIC; - fwrite(&magic, sizeof(uint32), 1, f); - - uint32 DataOffset = 5 * sizeof(uint32); - fwrite(&DataOffset, sizeof(uint32), 1, f); - - fwrite(&CompSize, sizeof(uint32), 1, f); - fwrite(&BufferSize, sizeof(uint32), 1, f); - - fwrite(CompBuffer, CompSize, 1, f); - } else { - _gameRef->LOG(0, "Error compressing data while saving '%s'", filename); - Compressed = false; - } - - delete [] CompBuffer; - } - } - - if (!Compressed) fwrite(Buffer, BufferSize, 1, f); - - fclose(f); -#endif - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::requestCD(int cd, char *packageFile, const char *filename) { - // unmount all non-local packages - for (uint32 i = 0; i < _packages.size(); i++) { - if (_packages[i]->_cD > 0) _packages[i]->close(); - } - - - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::addPath(TPathType type, const Common::String &path) { - if (path.c_str() == NULL || strlen(path.c_str()) < 1) return STATUS_FAILED; - - bool slashed = (path[path.size() - 1] == '\\' || path[path.size() - 1] == '/'); - - char *buffer = new char [strlen(path.c_str()) + 1 + (slashed ? 0 : 1)]; - if (buffer == NULL) return STATUS_FAILED; - - strcpy(buffer, path.c_str()); - if (!slashed) strcat(buffer, "\\"); - //CBPlatform::strlwr(buffer); - - switch (type) { - case PATH_SINGLE: - _singlePaths.push_back(buffer); - break; - case PATH_PACKAGE: - _packagePaths.push_back(buffer); - break; - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::reloadPaths() { - // delete registered paths - for (uint32 i = 0; i < _singlePaths.size(); i++) - delete [] _singlePaths[i]; - _singlePaths.clear(); - - for (uint32 i = 0; i < _packagePaths.size(); i++) - delete [] _packagePaths[i]; - _packagePaths.clear(); - - return initPaths(); -} - - -#define TEMP_BUFFER_SIZE 32768 -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::initPaths() { - restoreCurrentDir(); - - AnsiString pathList; - int numPaths; - - // single files paths - pathList = _gameRef->_registry->readString("Resource", "CustomPaths", ""); - numPaths = CBUtils::strNumEntries(pathList.c_str(), ';'); - - for (int i = 0; i < numPaths; i++) { - char *path = CBUtils::strEntry(i, pathList.c_str(), ';'); - if (path && strlen(path) > 0) { - addPath(PATH_SINGLE, path); - } - delete[] path; - path = NULL; - } - addPath(PATH_SINGLE, ".\\"); - - - // package files paths - addPath(PATH_PACKAGE, "./"); - - pathList = _gameRef->_registry->readString("Resource", "PackagePaths", ""); - numPaths = CBUtils::strNumEntries(pathList.c_str(), ';'); - - for (int i = 0; i < numPaths; i++) { - char *path = CBUtils::strEntry(i, pathList.c_str(), ';'); - if (path && strlen(path) > 0) { - addPath(PATH_PACKAGE, path); - } - delete[] path; - path = NULL; - } - addPath(PATH_PACKAGE, "data"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::registerPackages() { - restoreCurrentDir(); - - _gameRef->LOG(0, "Scanning packages..."); - debugC(kWinterMuteDebugFileAccess, "Scanning packages"); - - Common::ArchiveMemberList files; - SearchMan.listMatchingMembers(files, "*.dcp"); - - for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); it++) { - registerPackage((*it)->getName().c_str()); - } -#if 0 - AnsiString extension = AnsiString(PACKAGE_EXTENSION); - - for (int i = 0; i < _packagePaths.getSize(); i++) { - boost::filesystem::path absPath = boost::filesystem::syste_complete(_packagePaths[i]); - - //_gameRef->LOG(0, "Scanning: %s", absPath.string().c_str()); - //printf("Scanning: %s\n", absPath.string().c_str()); - - if (!exists(absPath)) continue; - - // scan files - boost::filesystem::directory_iterator endIter; - for (boost::filesystem::directory_iterator dit(absPath); dit != endIter; ++dit) { - if (!is_directory((*dit).status())) { - AnsiString fileName = (*dit).path().string(); - - if (!IsValidPackage(fileName)) continue; - - warning("%s", fileName.c_str()); - //printf("%s\n", fileName.c_str()); - if (!StringUtil::CompareNoCase(extension, PathUtil::GetExtension(fileName))) continue; - warning("Registered"); - RegisterPackage(absPath.string().c_str(), dit->path().filename().string().c_str()); - } - } - } -#endif - debugC(kWinterMuteDebugFileAccess, " Registered %d files in %d package(s)", _files.size(), _packages.size()); - _gameRef->LOG(0, " Registered %d files in %d package(s)", _files.size(), _packages.size()); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::registerPackage(const Common::String &filename , bool searchSignature) { -// FILE *f = fopen(filename, "rb"); - Common::File *package = new Common::File(); - package->open(filename); - if (!package->isOpen()) { - _gameRef->LOG(0, " Error opening package file '%s'. Ignoring.", filename.c_str()); - return STATUS_OK; - } - - uint32 absoluteOffset = 0; - bool boundToExe = false; - - if (searchSignature) { - uint32 offset; - if (!findPackageSignature(package, &offset)) { - delete package; - return STATUS_OK; - } else { - package->seek(offset, SEEK_SET); - absoluteOffset = offset; - boundToExe = true; - } - } - - TPackageHeader hdr; - hdr.readFromStream(package); -// package->read(&hdr, sizeof(TPackageHeader), 1, f); - if (hdr.Magic1 != PACKAGE_MAGIC_1 || hdr.Magic2 != PACKAGE_MAGIC_2 || hdr.PackageVersion > PACKAGE_VERSION) { - _gameRef->LOG(0, " Invalid header in package file '%s'. Ignoring.", filename.c_str()); - delete package; - return STATUS_OK; - } - - if (hdr.PackageVersion != PACKAGE_VERSION) { - _gameRef->LOG(0, " Warning: package file '%s' is outdated.", filename.c_str()); - } - - // new in v2 - if (hdr.PackageVersion == PACKAGE_VERSION) { - uint32 dirOffset; - dirOffset = package->readUint32LE(); - dirOffset += absoluteOffset; - package->seek(dirOffset, SEEK_SET); - } - - for (uint32 i = 0; i < hdr.NumDirs; i++) { - CBPackage *pkg = new CBPackage(_gameRef); - if (!pkg) return STATUS_FAILED; - - pkg->_boundToExe = boundToExe; - - // read package info - byte nameLength = package->readByte(); - pkg->_name = new char[nameLength]; - package->read(pkg->_name, nameLength); - pkg->_cD = package->readByte(); - pkg->_priority = hdr.Priority; - - if (!hdr.MasterIndex) pkg->_cD = 0; // override CD to fixed disk - _packages.push_back(pkg); - - - // read file entries - uint32 NumFiles = package->readUint32LE(); - - for (uint32 j = 0; j < NumFiles; j++) { - char *name; - uint32 offset, length, compLength, flags, timeDate1, timeDate2; - - nameLength = package->readByte(); - name = new char[nameLength]; - package->read(name, nameLength); - - // v2 - xor name - if (hdr.PackageVersion == PACKAGE_VERSION) { - for (int k = 0; k < nameLength; k++) { - ((byte *)name)[k] ^= 'D'; - } - } - - // some old version of ProjectMan writes invalid directory entries - // so at least prevent strupr from corrupting memory - name[nameLength - 1] = '\0'; - - - CBPlatform::strupr(name); - - offset = package->readUint32LE(); - offset += absoluteOffset; - length = package->readUint32LE(); - compLength = package->readUint32LE(); - flags = package->readUint32LE(); - - if (hdr.PackageVersion == PACKAGE_VERSION) { - timeDate1 = package->readUint32LE(); - timeDate2 = package->readUint32LE(); - } - _filesIter = _files.find(name); - if (_filesIter == _files.end()) { - CBFileEntry *file = new CBFileEntry(_gameRef); - file->_package = pkg; - file->_offset = offset; - file->_length = length; - file->_compressedLength = compLength; - file->_flags = flags; - - _files[name] = file; - } else { - // current package has lower CD number or higher priority, than the registered - if (pkg->_cD < _filesIter->_value->_package->_cD || pkg->_priority > _filesIter->_value->_package->_priority) { - _filesIter->_value->_package = pkg; - _filesIter->_value->_offset = offset; - _filesIter->_value->_length = length; - _filesIter->_value->_compressedLength = compLength; - _filesIter->_value->_flags = flags; - } - } - delete [] name; - } - } - - - delete package; - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::isValidPackage(const AnsiString &fileName) const { - AnsiString plainName = PathUtil::getFileNameWithoutExtension(fileName); - - // check for device-type specific packages - if (StringUtil::startsWith(plainName, "xdevice_", true)) { - return StringUtil::compareNoCase(plainName, "xdevice_" + _gameRef->getDeviceType()); - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -Common::File *CBFileManager::openPackage(const Common::String &name) { - //TODO: Is it really necessary to do this when we have the ScummVM-system? - - //RestoreCurrentDir(); - - Common::File *ret = new Common::File(); - char filename[MAX_PATH_LENGTH]; - - for (uint32 i = 0; i < _packagePaths.size(); i++) { - sprintf(filename, "%s%s.%s", _packagePaths[i], name.c_str(), PACKAGE_EXTENSION); - ret->open(filename); - if (ret->isOpen()) { - return ret; - } - } - - sprintf(filename, "%s.%s", name.c_str(), PACKAGE_EXTENSION); - ret->open(filename); - if (ret->isOpen()) { - return ret; - } - warning("CBFileManager::OpenPackage - Couldn't load file %s", name.c_str()); - delete ret; - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -Common::File *CBFileManager::openSingleFile(const Common::String &name) { - restoreCurrentDir(); - - Common::File *ret = NULL; - char filename[MAX_PATH_LENGTH]; - - for (uint32 i = 0; i < _singlePaths.size(); i++) { - sprintf(filename, "%s%s", _singlePaths[i], name.c_str()); - ret->open(filename); - if (ret->isOpen()) - return ret; - } - - // didn't find in search paths, try to open directly - ret->open(name); - if (ret->isOpen()) { - return ret; - } else { - delete ret; - return NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::getFullPath(const Common::String &filename, char *fullname) { - restoreCurrentDir(); - - Common::File f; - bool found = false; - - for (uint32 i = 0; i < _singlePaths.size(); i++) { - sprintf(fullname, "%s%s", _singlePaths[i], filename.c_str()); - f.open(fullname); - if (f.isOpen()) { - f.close(); - found = true; - break; - } - } - - if (!found) { - f.open(filename.c_str()); - if (f.isOpen()) { - f.close(); - found = true; - strcpy(fullname, filename.c_str()); - } - } - - return found; -} - - -////////////////////////////////////////////////////////////////////////// -CBFileEntry *CBFileManager::getPackageEntry(const Common::String &filename) { - char *upc_name = new char[strlen(filename.c_str()) + 1]; - strcpy(upc_name, filename.c_str()); - CBPlatform::strupr(upc_name); - - CBFileEntry *ret = NULL; - _filesIter = _files.find(upc_name); - if (_filesIter != _files.end()) ret = _filesIter->_value; - - delete [] upc_name; - - return ret; -} - -bool CBFileManager::hasFile(const Common::String &filename) { - //TODO: Do this in a much simpler fashion - Common::SeekableReadStream *stream = openFile(filename, true, false); - if (!stream) { - return false; - } - delete stream; - return true; -} - -////////////////////////////////////////////////////////////////////////// -Common::SeekableReadStream *CBFileManager::openFile(const Common::String &filename, bool absPathWarning, bool keepTrackOf) { - if (strcmp(filename.c_str(), "") == 0) return NULL; - //_gameRef->LOG(0, "open file: %s", filename); - /*#ifdef __WIN32__ - if (_gameRef->_debugDebugMode && _gameRef->_debugAbsolutePathWarning && AbsPathWarning) { - char Drive[_MAX_DRIVE]; - _splitpath(filename, Drive, NULL, NULL, NULL); - if (Drive[0] != '\0') { - _gameRef->LOG(0, "WARNING: Referencing absolute path '%s'. The game will NOT work on another computer.", filename); - } - } - #endif*/ - - Common::SeekableReadStream *file = openFileRaw(filename); - if (file && keepTrackOf) _openFiles.push_back(file); - return file; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::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 *CBFileManager::openFileRaw(const Common::String &filename) { - restoreCurrentDir(); - - Common::SeekableReadStream *ret = NULL; - - if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) { - CBSaveThumbFile *SaveThumbFile = new CBSaveThumbFile(_gameRef); - if (DID_SUCCEED(SaveThumbFile->open(filename))) { - ret = SaveThumbFile->getMemStream(); - } - delete SaveThumbFile; - return ret; - } - - - - ret = openDiskFile(filename, this); - if (ret) return ret; - - ret = openPkgFile(filename, this); - if (ret) return ret; - - ret = CBResources::getFile(filename); - if (ret) return ret; - - warning("BFileManager::OpenFileRaw - Failed to open %s", filename.c_str()); - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::restoreCurrentDir() { - if (!_basePath) return STATUS_OK; - else { - /*if (!chdir(_basePath)) return STATUS_OK; - else return STATUS_FAILED;*/ - warning("CBFileManager::RestoreCurrentDir - ignored"); - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::setBasePath(const Common::String &path) { - cleanup(); - - if (path.c_str()) { - _basePath = new char[path.size() + 1]; - strcpy(_basePath, path.c_str()); - } - - initPaths(); - registerPackages(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFileManager::findPackageSignature(Common::File *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; - -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BFileManager.h b/engines/wintermute/base/BFileManager.h deleted file mode 100644 index 7ea9ff5611..0000000000 --- a/engines/wintermute/base/BFileManager.h +++ /dev/null @@ -1,85 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFILEMANAGER_H -#define WINTERMUTE_BFILEMANAGER_H - -#include "engines/wintermute/base/file/BFileEntry.h" -#include "common/archive.h" -#include "common/str.h" - -namespace Common { -class File; -} - -namespace WinterMute { -class CBFile; -class CBFileManager: CBBase { -public: - bool findPackageSignature(Common::File *f, uint32 *offset); - bool cleanup(); - bool setBasePath(const Common::String &path); - bool restoreCurrentDir(); - char *_basePath; - bool getFullPath(const Common::String &filename, char *fullname); - Common::SeekableReadStream *openFileRaw(const Common::String &filename); - bool closeFile(Common::SeekableReadStream *File); - bool hasFile(const Common::String &filename); - Common::SeekableReadStream *openFile(const Common::String &filename, bool absPathWarning = true, bool keepTrackOf = true); - CBFileEntry *getPackageEntry(const Common::String &filename); - Common::File *openSingleFile(const Common::String &name); - Common::File *openPackage(const Common::String &name); - bool registerPackages(); - bool initPaths(); - bool reloadPaths(); - typedef enum { - PATH_PACKAGE, PATH_SINGLE - } TPathType; - bool addPath(TPathType type, const Common::String &path); - bool requestCD(int cd, char *packageFile, const char *filename); - Common::SeekableReadStream *loadSaveGame(const Common::String &filename); - bool saveFile(const Common::String &filename, byte *buffer, uint32 bufferSize, bool compressed = false, byte *prefixBuffer = NULL, uint32 prefixSize = 0); - byte *readWholeFile(const Common::String &filename, uint32 *size = NULL, bool mustExist = true); - CBFileManager(CBGame *inGame = NULL); - virtual ~CBFileManager(); - Common::Array _singlePaths; - Common::Array _packagePaths; - Common::Array _packages; - Common::Array _openFiles; - - Common::HashMap _files; -private: - bool registerPackage(const Common::String &filename, bool searchSignature = false); - Common::HashMap::iterator _filesIter; - bool isValidPackage(const AnsiString &fileName) const; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BFrame.cpp b/engines/wintermute/base/BFrame.cpp deleted file mode 100644 index d6d8a3aa5c..0000000000 --- a/engines/wintermute/base/BFrame.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BParser.h" -#include "engines/wintermute/base/BFrame.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BSubFrame.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "common/str.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBFrame, false) - -////////////////////////////////////////////////////////////////////// -CBFrame::CBFrame(CBGame *inGame): CBScriptable(inGame, true) { - _delay = 0; - _moveX = _moveY = 0; - - _sound = NULL; - _killSound = false; - - _editorExpanded = false; - _keyframe = false; -} - - -////////////////////////////////////////////////////////////////////// -CBFrame::~CBFrame() { - delete _sound; - _sound = NULL; - - for (int i = 0; i < _subframes.getSize(); i++) - delete _subframes[i]; - _subframes.removeAll(); - - for (int i = 0; i < _applyEvent.getSize(); i++) { - delete[] _applyEvent[i]; - _applyEvent[i] = NULL; - } - _applyEvent.removeAll(); -} - - -////////////////////////////////////////////////////////////////////// -bool CBFrame::draw(int x, int y, CBObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, bool allFrames, float rotate, TSpriteBlendMode blendMode) { - bool res; - - for (int i = 0; i < _subframes.getSize(); i++) { - res = _subframes[i]->draw(x, y, registerOwner, zoomX, zoomY, precise, alpha, rotate, blendMode); - if (DID_FAIL(res)) return res; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFrame::oneTimeDisplay(CBObject *owner, bool muted) { - if (_sound && !muted) { - if (owner) owner->updateOneSound(_sound); - _sound->play(); - /* - if (_gameRef->_state == GAME_FROZEN) { - _sound->Pause(true); - } - */ - } - if (owner) { - for (int i = 0; i < _applyEvent.getSize(); 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 CBFrame::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; - CBParser parser(_gameRef); - 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; - CBPlatform::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: { - CBSubFrame *subframe = new CBSubFrame(_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 CBSound(_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; - } - - - CBSubFrame *sub = new CBSubFrame(_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 (CBPlatform::isRectEmpty(&rect)) sub->setDefaultRect(); - else sub->_rect = 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.insertAt(0, sub); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFrame::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float scaleY) { - if (!rect) return false; - CBPlatform::setRectEmpty(rect); - - Rect32 subRect; - - for (int i = 0; i < _subframes.getSize(); i++) { - _subframes[i]->getBoundingRect(&subRect, x, y, scaleX, scaleY); - CBPlatform::unionRect(rect, rect, &subRect); - } - return true; -} - - - -////////////////////////////////////////////////////////////////////////// -bool CBFrame::saveAsText(CBDynBuffer *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->_soundFilename) - buffer->putTextIndent(indent + 2, "SOUND=\"%s\"\n", _sound->_soundFilename); - - 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.getSize() > 0) _subframes[0]->saveAsText(buffer, indent, false); - - for (int i = 1; i < _subframes.getSize(); i++) { - _subframes[i]->saveAsText(buffer, indent + 2); - } - - for (int i = 0; i < _applyEvent.getSize(); i++) { - buffer->putTextIndent(indent + 2, "APPLY_EVENT=\"%s\"\n", _applyEvent[i]); - } - - CBBase::saveAsText(buffer, indent + 2); - - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFrame::persist(CBPersistMgr *persistMgr) { - CBScriptable::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 CBFrame::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - - ////////////////////////////////////////////////////////////////////////// - // GetSound - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GetSound") == 0) { - stack->correctParams(0); - - if (_sound && _sound->_soundFilename) stack->pushString(_sound->_soundFilename); - else stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetSound - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetSound") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - delete _sound; - _sound = NULL; - - if (!val->isNULL()) { - _sound = new CBSound(_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 >= _subframes.getSize()) { - 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); - CScValue *val = stack->pop(); - if (val->isInt()) { - int index = val->getInt(-1); - if (index < 0 || index >= _subframes.getSize()) { - script->runtimeError("Frame.DeleteSubframe: Subframe index %d is out of range.", index); - } - } else { - CBSubFrame *sub = (CBSubFrame *)val->getNative(); - for (int i = 0; i < _subframes.getSize(); i++) { - if (_subframes[i] == sub) { - delete _subframes[i]; - _subframes.removeAt(i); - break; - } - } - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddSubframe - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddSubframe") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - const char *filename = NULL; - if (!val->isNULL()) filename = val->getString(); - - CBSubFrame *sub = new CBSubFrame(_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; - - CScValue *val = stack->pop(); - const char *filename = NULL; - if (!val->isNULL()) filename = val->getString(); - - CBSubFrame *sub = new CBSubFrame(_gameRef); - if (filename != NULL) { - sub->setSurface(filename); - } - - if (index >= _subframes.getSize()) _subframes.add(sub); - else _subframes.insertAt(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 >= _applyEvent.getSize()) { - 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 (int i = 0; i < _applyEvent.getSize(); 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 (int i = 0; i < _applyEvent.getSize(); i++) { - if (scumm_stricmp(_applyEvent[i], event) == 0) { - delete [] _applyEvent[i]; - _applyEvent.removeAt(i); - break; - } - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - else { - if (_subframes.getSize() == 1) return _subframes[0]->scCallMethod(script, stack, thisStack, name); - else return CBScriptable::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBFrame::scGetProperty(const char *name) { - if (!_scValue) _scValue = new CScValue(_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.getSize()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumEvents (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumEvents") == 0) { - _scValue->setInt(_applyEvent.getSize()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - else { - if (_subframes.getSize() == 1) return _subframes[0]->scGetProperty(name); - else return CBScriptable::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFrame::scSetProperty(const char *name, CScValue *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.getSize() == 1) return _subframes[0]->scSetProperty(name, value); - else return CBScriptable::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBFrame::scToString() { - return "[frame]"; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BFrame.h b/engines/wintermute/base/BFrame.h deleted file mode 100644 index 3d487b4ebc..0000000000 --- a/engines/wintermute/base/BFrame.h +++ /dev/null @@ -1,73 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFRAME_H -#define WINTERMUTE_BFRAME_H - -#include "engines/wintermute/base/BScriptable.h" -#include "engines/wintermute/coll_templ.h" - -namespace WinterMute { -class CBSound; -class CBSubFrame; -class CBObject; -class CScScript; -class CScStack; -class CBFrame: public CBScriptable { -public: - bool _killSound; - bool _keyframe; - bool oneTimeDisplay(CBObject *owner, bool muted = false); - DECLARE_PERSISTENT(CBFrame, CBScriptable) - CBSound *_sound; - bool _editorExpanded; - bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100); - bool saveAsText(CBDynBuffer *buffer, int indent); - int _moveY; - int _moveX; - uint32 _delay; - CBArray _subframes; - bool draw(int x, int y, CBObject *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); - - CBFrame(CBGame *inGame); - virtual ~CBFrame(); - - CBArray _applyEvent; - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BGame.cpp b/engines/wintermute/base/BGame.cpp deleted file mode 100644 index 3e577541b7..0000000000 --- a/engines/wintermute/base/BGame.cpp +++ /dev/null @@ -1,4478 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/base/BFader.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/font/BFontStorage.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/BKeyboardState.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BQuickMsg.h" -#include "engines/wintermute/base/BRegistry.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BSubFrame.h" - -#include "engines/wintermute/base/BTransitionMgr.h" -#include "engines/wintermute/base/BViewport.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/base/BSaveThumbHelper.h" -#include "engines/wintermute/base/BSurfaceStorage.h" -#include "engines/wintermute/utils/crc.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/ui/UIWindow.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/SXMath.h" -#include "engines/wintermute/video/VidPlayer.h" -#include "engines/wintermute/video/VidTheoraPlayer.h" -#include "engines/wintermute/wintermute.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(CBGame, true) - - -////////////////////////////////////////////////////////////////////// -CBGame::CBGame(): CBObject(this) { - _shuttingDown = false; - - _state = GAME_RUNNING; - _origState = GAME_RUNNING; - _freezeLevel = 0; - - _interactive = true; - _origInteractive = false; - - _surfaceStorage = NULL; - _fontStorage = NULL; - _renderer = NULL; - _soundMgr = NULL; - _fileManager = NULL; - _transMgr = NULL; - _debugMgr = NULL; - _scEngine = NULL; - _keyboardState = NULL; - - _mathClass = NULL; - - _debugLogFile = NULL; - _debugDebugMode = false; - _debugAbsolutePathWarning = true; - _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; - - _registry = new CBRegistry(this); - _stringTable = new CBStringTable(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; - - _indicatorDisplay = false; - _indicatorColor = BYTETORGBA(255, 0, 0, 128); - _indicatorProgress = 0; - _indicatorX = -1; - _indicatorY = -1; - _indicatorWidth = -1; - _indicatorHeight = 8; - _richSavedGames = false; - _savedGameExt = NULL; - CBUtils::setString(&_savedGameExt, "dsv"); - - _musicCrossfadeRunning = false; - _musicCrossfadeStartTime = 0; - _musicCrossfadeLength = 0; - _musicCrossfadeChannel1 = -1; - _musicCrossfadeChannel2 = -1; - _musicCrossfadeSwap = false; - - _loadImageName = NULL; - _saveImageName = NULL; - _saveLoadImage = NULL; - - _saveImageX = _saveImageY = 0; - _loadImageX = _loadImageY = 0; - - _localSaveDir = NULL; - CBUtils::setString(&_localSaveDir, "saves"); - _saveDirChecked = false; - - _loadingIcon = NULL; - _loadingIconX = _loadingIconY = 0; - _loadingIconPersistent = false; - - _textEncoding = TEXT_ANSI; - _textRTL = false; - - _soundBufferSizeSec = 3; - _suspendedRendering = false; - - _lastCursor = NULL; - - - CBPlatform::setRectEmpty(&_mouseLockRect); - - _suppressScriptErrors = false; - _lastMiniUpdate = 0; - _miniUpdateEnabled = false; - - _cachedThumbnail = NULL; - - _autorunDisabled = false; - - // compatibility bits - _compatKillMethodThreads = false; - - _usedMem = 0; - - - _autoSaveOnExit = true; - _autoSaveSlot = 999; - _cursorHidden = false; - -/*#ifdef __IPHONEOS__ - _touchInterface = true; - _constrainedMemory = true; // TODO differentiate old and new iOS devices -#else*/ - _touchInterface = false; - _constrainedMemory = false; -//#endif - -} - - -////////////////////////////////////////////////////////////////////// -CBGame::~CBGame() { - _shuttingDown = true; - - LOG(0, ""); - LOG(0, "Shutting down..."); - - getDebugMgr()->onGameShutdown(); - - _registry->writeBool("System", "LastRun", true); - - cleanup(); - - delete[] _localSaveDir; - delete[] _settingsGameFile; - delete[] _savedGameExt; - - delete _cachedThumbnail; - - delete _saveLoadImage; - delete _mathClass; - - delete _transMgr; - delete _scEngine; - delete _fontStorage; - delete _surfaceStorage; - delete _videoPlayer; - delete _theoraPlayer; - delete _soundMgr; - delete _debugMgr; - //SAFE_DELETE(_keyboardState); - - delete _renderer; - delete _fileManager; - delete _registry; - delete _stringTable; - - _localSaveDir = NULL; - _settingsGameFile = NULL; - _savedGameExt = NULL; - - _cachedThumbnail = NULL; - - _saveLoadImage = NULL; - _mathClass = NULL; - - _transMgr = NULL; - _scEngine = NULL; - _fontStorage = NULL; - _surfaceStorage = NULL; - _videoPlayer = NULL; - _theoraPlayer = NULL; - _soundMgr = NULL; - _debugMgr = NULL; - - _renderer = NULL; - _fileManager = NULL; - _registry = NULL; - _stringTable = NULL; - - DEBUG_DebugDisable(); - CBPlatform::outputDebugString("--- shutting down normally ---\n"); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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 (int i = 0; i < _regObjects.getSize(); i++) { - delete _regObjects[i]; - _regObjects[i] = NULL; - } - _regObjects.removeAll(); - - _windows.removeAll(); // refs only - _focusedWindow = NULL; // ref only - - delete[] _saveImageName; - delete[] _loadImageName; - _saveImageName = NULL; - _loadImageName = NULL; - - delete _cursorNoninteractive; - delete _cursor; - delete _activeCursor; - _cursorNoninteractive = NULL; - _cursor = NULL; - _activeCursor = NULL; - - delete _scValue; - delete _sFX; - _scValue = NULL; - _sFX = NULL; - - for (int i = 0; i < _scripts.getSize(); i++) { - _scripts[i]->_owner = NULL; - _scripts[i]->finish(); - } - _scripts.removeAll(); - - _fontStorage->removeFont(_systemFont); - _systemFont = NULL; - - _fontStorage->removeFont(_videoFont); - _videoFont = NULL; - - for (int i = 0; i < _quickMessages.getSize(); i++) delete _quickMessages[i]; - _quickMessages.removeAll(); - - _viewportStack.removeAll(); - _viewportSP = -1; - - delete[] _name; - delete[] _filename; - _name = NULL; - _filename = NULL; - for (int i = 0; i < 7; i++) { - delete[] _caption[i]; - _caption[i] = NULL; - } - - _lastCursor = NULL; - - delete _keyboardState; - _keyboardState = NULL; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////// -bool CBGame::initialize1() { - bool loaded = false; // Not really a loop, but a goto-replacement. - while (!loaded) { - _surfaceStorage = new CBSurfaceStorage(this); - if (_surfaceStorage == NULL) - break; - - _fontStorage = new CBFontStorage(this); - if (_fontStorage == NULL) - break; - - _fileManager = new CBFileManager(this); - if (_fileManager == NULL) - break; - - _soundMgr = new CBSoundMgr(this); - if (_soundMgr == NULL) - break; - - _debugMgr = new CBDebugger(this); - if (_debugMgr == NULL) - break; - - _mathClass = new CSXMath(this); - if (_mathClass == NULL) - break; - - _scEngine = new CScEngine(this); - if (_scEngine == NULL) - break; - - _videoPlayer = new CVidPlayer(this); - if (_videoPlayer == NULL) - break; - - _transMgr = new CBTransitionMgr(this); - if (_transMgr == NULL) - break; - - _keyboardState = new CBKeyboardState(this); - if (_keyboardState == NULL) - break; - - _fader = new CBFader(this); - if (_fader == NULL) - break; - registerObject(_fader); - - loaded = true; - } - if (loaded == true) { - return STATUS_OK; - } else { - delete _mathClass; - delete _keyboardState; - delete _transMgr; - delete _debugMgr; - delete _surfaceStorage; - delete _fontStorage; - delete _soundMgr; - delete _fileManager; - delete _scEngine; - delete _videoPlayer; - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////// -bool CBGame::initialize2() { // we know whether we are going to be accelerated - _renderer = makeOSystemRenderer(this); - if (_renderer == NULL) return STATUS_FAILED; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////// -bool CBGame::initialize3() { // renderer is initialized - _posX = _renderer->_width / 2; - _posY = _renderer->_height / 2; - - if (_indicatorY == -1) _indicatorY = _renderer->_height - _indicatorHeight; - if (_indicatorX == -1) _indicatorX = 0; - if (_indicatorWidth == -1) _indicatorWidth = _renderer->_width; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////// -void CBGame::DEBUG_DebugEnable(const char *filename) { - _debugDebugMode = true; - - /* time_t timeNow; - time(&timeNow); - struct tm *tm = localtime(&timeNow); - - #ifdef _DEBUG - LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%04d (Debug Build) *******************", tm->tm_mday, tm->tm_mon, tm->tm_year + 1900); - #else - LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%04d (Release Build) *****************", tm->tm_mday, tm->tm_mon, tm->tm_year + 1900); - #endif*/ - 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); - //LOG(0, "Extensions: %s ver %d.%02d", EXT_NAME, EXT_VER_MAJOR, EXT_VER_MINOR); - - AnsiString platform = CBPlatform::getPlatformName(); - LOG(0, "Platform: %s", platform.c_str()); - LOG(0, ""); -} - - -////////////////////////////////////////////////////////////////////// -void CBGame::DEBUG_DebugDisable() { - if (_debugLogFile != NULL) { - LOG(0, "********** DEBUG LOG CLOSED ********************************************"); - //fclose((FILE *)_debugLogFile); - _debugLogFile = NULL; - } - _debugDebugMode = false; -} - - -////////////////////////////////////////////////////////////////////// -void CBGame::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); - } - if (_debugMgr) _debugMgr->onLog(res, buff); - - 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 CBGame::setEngineLogCallback(ENGINE_LOG_CALLBACK callback, void *data) { - _engineLogCallback = callback; - _engineLogCallbackData = data; -} - - -////////////////////////////////////////////////////////////////////// -bool CBGame::initLoop() { - _viewportSP = -1; - - _currentTime = CBPlatform::getTime(); - - getDebugMgr()->onGameTick(); - _renderer->initLoop(); - _soundMgr->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.getSize() - 1; i >= 0; i--) { - if (_windows[i]->_visible) { - _focusedWindow = _windows[i]; - break; - } - } - - updateSounds(); - - if (_fader) _fader->update(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////// -bool CBGame::initInput() { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CBGame::getSequence() { - return ++_sequence; -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::setOffset(int offsetX, int offsetY) { - _offsetX = offsetX; - _offsetY = offsetY; -} - -////////////////////////////////////////////////////////////////////////// -void CBGame::getOffset(int *offsetX, int *offsetY) { - if (offsetX != NULL) *offsetX = _offsetX; - if (offsetY != NULL) *offsetY = _offsetY; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CBGame::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CBGame::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 - - byte *params; - int cmd; - CBParser parser(_gameRef); - - 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 CBSprite(_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 CBSprite(_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 CBSprite(_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: - CBUtils::setString(&_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: - CBUtils::setString(&_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: - CBUtils::setString(&_localSaveDir, (char *)params); - break; - - case TOKEN_COMPAT_KILL_METHOD_THREADS: - parser.scanStr((char *)params, "%b", &_compatKillMethodThreads); - break; - } - } - - 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 CBGame::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 = CBObject::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(); - CScValue *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); - CBScriptable *obj = stack->pop()->getNative(); - if (validObject((CBObject *) 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); - CScValue *val = stack->pop(); - CBObject *obj = (CBObject *)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); - CUIWindow *win = new CUIWindow(_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); - CScValue *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(); - CScValue *valLooping = stack->pop(); - bool looping = valLooping->isNULL() ? true : valLooping->getBool(); - - CScValue *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]->_soundFilename) stack->pushNULL(); - else stack->pushString(_music[channel]->_soundFilename); - } - 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(); - - CBSound *sound = new CBSound(_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; - - CBPlatform::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) CBUtils::swap(&left, &right); - if (bottom < top) CBUtils::swap(&top, &bottom); - - CBPlatform::setRect(&_mouseLockRect, left, top, right, bottom); - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // PlayVideo - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PlayVideo") == 0) { - /* stack->correctParams(0); - stack->pushBool(false); - - return STATUS_OK; - // TODO: ADDVIDEO - */ - - _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); - CScValue *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); - - CScValue *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(0); - stack->pushBool(false); - - return STATUS_OK;*/ - // TODO: ADDVIDEO - - stack->correctParams(7); - const char *filename = stack->pop()->getString(); - CScValue *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); - - CScValue *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 CVidTheoraPlayer(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(); - _registry->writeInt("PrivateSettings", key, 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(); - stack->pushInt(_registry->readInt("PrivateSettings", key, initVal)); - 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(); - _registry->writeString("PrivateSettings", key, val); - 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(); - AnsiString val = _registry->readString("PrivateSettings", key, initVal); - stack->pushString(val.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(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'; - getSaveSlotDescription(slot, desc); - stack->pushString(desc); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // EmptySaveSlot - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "EmptySaveSlot") == 0) { - stack->correctParams(1); - int slot = stack->pop()->getInt(); - 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->_filename) stack->pushNULL(); - else stack->pushString(_activeCursor->_filename); - - 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(); - - // TODO: Replace with fileExists - Common::SeekableReadStream *file = _fileManager->openFile(filename, false); - if (!file) stack->pushBool(false); - else { - _fileManager->closeFile(file); - stack->pushBool(true); - } - 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]; - - CScValue *Val = stack->pop(); - - warning("BGame::ScCallMethod - Screenshot not reimplemented"); //TODO - int fileNum = 0; - - while (true) { - sprintf(filename, "%s%03d.bmp", Val->isNULL() ? _name : Val->getString(), fileNum); - if (!Common::File::exists(filename)) - break; - fileNum++; - } - - bool ret = false; - CBImage *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; - CBImage *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); - CScValue *val = stack->pop(); - - CUIWindow *win = new CUIWindow(_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); - CBObject *obj = (CBObject *)stack->pop()->getNative(); - for (int i = 0; i < _windows.getSize(); 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); - CScValue *val = stack->pop(); - _loadImageX = stack->pop()->getInt(); - _loadImageY = stack->pop()->getInt(); - - if (val->isNULL()) { - delete[] _loadImageName; - _loadImageName = NULL; - } else { - CBUtils::setString(&_loadImageName, val->getString()); - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetSavingScreen - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetSavingScreen") == 0) { - stack->correctParams(3); - CScValue *val = stack->pop(); - _saveImageX = stack->pop()->getInt(); - _saveImageY = stack->pop()->getInt(); - - if (val->isNULL()) { - delete[] _saveImageName; - _saveImageName = NULL; - } else { - CBUtils::setString(&_saveImageName, val->getString()); - } - 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->_filename) stack->pushNULL(); - else stack->pushString(_cursorNoninteractive->_filename); - - 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 CBSprite(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 CBSaveThumbHelper(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 = _fileManager->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); - - _fileManager->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); -/*#ifdef __IPHONEOS__ - IOS_ShowStatusLine(TRUE); -#endif*/ - stack->pushNULL(); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // HideStatusLine - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "HideStatusLine") == 0) { - stack->correctParams(0); -/*#ifdef __IPHONEOS__ - IOS_ShowStatusLine(FALSE); -#endif*/ - stack->pushNULL(); - - return STATUS_OK; - } - - else return CBObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBGame::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(_name); - 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)CBPlatform::getTime()); - 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 = getDataDir(); - _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(CBPlatform::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) { - _scValue->setInt(_registry->readInt("System", "MostRecentSaveSlot", -1)); - 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 CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::scSetProperty(const char *name, CScValue *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 = CBObject::scSetProperty(name, value); - setWindowTitle(); - return res; - } - - ////////////////////////////////////////////////////////////////////////// - // MainObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MainObject") == 0) { - CBScriptable *obj = value->getNative(); - if (obj == NULL || validObject((CBObject *)obj)) _mainObject = (CBObject *)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 CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBGame::scToString() { - return "[game object]"; -} - - - -#define QUICK_MSG_DURATION 3000 -////////////////////////////////////////////////////////////////////////// -bool CBGame::displayQuickMsg() { - if (_quickMessages.getSize() == 0 || !_systemFont) return STATUS_OK; - - // update - for (int i = 0; i < _quickMessages.getSize(); i++) { - if (_currentTime - _quickMessages[i]->_startTime >= QUICK_MSG_DURATION) { - delete _quickMessages[i]; - _quickMessages.removeAt(i); - i--; - } - } - - int posY = 20; - - // display - for (int i = 0; i < _quickMessages.getSize(); 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 CBGame::quickMessage(const char *text) { - if (_quickMessages.getSize() >= MAX_QUICK_MSG) { - delete _quickMessages[0]; - _quickMessages.removeAt(0); - } - _quickMessages.add(new CBQuickMsg(_gameRef, text)); -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::quickMessageForm(char *fmt, ...) { - char buff[256]; - va_list va; - - va_start(va, fmt); - vsprintf(buff, fmt, va); - va_end(va); - - quickMessage(buff); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::registerObject(CBObject *object) { - _regObjects.add(object); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::unregisterObject(CBObject *object) { - if (!object) return STATUS_OK; - - // is it a window? - for (int i = 0; i < _windows.getSize(); i++) { - if ((CBObject *)_windows[i] == object) { - _windows.removeAt(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 (int i = 0; i < _regObjects.getSize(); i++) { - if (_regObjects[i] == object) { - _regObjects.removeAt(i); - if (!_loadInProgress) CSysClassRegistry::getInstance()->enumInstances(invalidateValues, "CScValue", (void *)object); - delete object; - return STATUS_OK; - } - } - - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::invalidateValues(void *value, void *data) { - CScValue *val = (CScValue *)value; - if (val->isNative() && val->getNative() == data) { - if (!val->_persistent && ((CBScriptable *)data)->_refCount == 1) { - ((CBScriptable *)data)->_refCount++; - } - val->setNative(NULL); - val->setNULL(); - } -} - - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::validObject(CBObject *object) { - if (!object) return false; - if (object == this) return true; - - for (int i = 0; i < _regObjects.getSize(); i++) { - if (_regObjects[i] == object) return true; - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name) { - CScValue *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); - - CBScriptable *obj = stack->pop()->getNative(); - if (validObject((CBObject *)obj)) script->waitForExclusive((CBObject *)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(CBUtils::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; - CScValue *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(CBUtils::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; - CBUtils::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; - CBUtils::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; - CBUtils::RGBtoHSL(rgb, &H, &S, &L); - stack->pushInt(L); - } - - ////////////////////////////////////////////////////////////////////////// - // Debug - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Debug") == 0) { - stack->correctParams(0); - - if (_gameRef->getDebugMgr()->_enabled) { - _gameRef->getDebugMgr()->onScriptHitBreakpoint(script); - script->sleep(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 CBGame::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 CBGame::SaveGame(int slot, const char *desc, bool quickSave) { - char filename[MAX_PATH_LENGTH + 1]; - getSaveSlotFilename(slot, filename); - - LOG(0, "Saving game '%s'...", filename); - - _gameRef->applyEvent("BeforeSave", true); - - bool ret; - - _indicatorDisplay = true; - _indicatorProgress = 0; - CBPersistMgr *pm = new CBPersistMgr(_gameRef); - if (DID_FAIL(ret = pm->initSave(desc))) goto save_finish; - - if (!quickSave) { - delete _saveLoadImage; - _saveLoadImage = NULL; - if (_saveImageName) { - _saveLoadImage = _renderer->createSurface(); - - if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_saveImageName, true, 0, 0, 0))) { - delete _saveLoadImage; - _saveLoadImage = NULL; - } - } - } - - if (DID_FAIL(ret = CSysClassRegistry::getInstance()->saveTable(_gameRef, pm, quickSave))) goto save_finish; - if (DID_FAIL(ret = CSysClassRegistry::getInstance()->saveInstances(_gameRef, pm, quickSave))) goto save_finish; - if (DID_FAIL(ret = pm->saveFile(filename))) goto save_finish; - - _registry->writeInt("System", "MostRecentSaveSlot", slot); - -save_finish: // TODO: Remove gotos - delete pm; - _indicatorDisplay = false; - - delete _saveLoadImage; - _saveLoadImage = NULL; - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::loadGame(int slot) { - //_gameRef->LOG(0, "Load start %d", CBUtils::GetUsedMemMB()); - - _loading = false; - _scheduledLoadSlot = -1; - - char filename[MAX_PATH_LENGTH + 1]; - getSaveSlotFilename(slot, filename); - - return loadGame(filename); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::loadGame(const char *filename) { - LOG(0, "Loading game '%s'...", filename); - getDebugMgr()->onGameShutdown(); - - bool ret; - - delete _saveLoadImage; - _saveLoadImage = NULL; - if (_loadImageName) { - _saveLoadImage = _renderer->createSurface(); - - if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_loadImageName, true, 0, 0, 0))) { - delete _saveLoadImage; - _saveLoadImage = NULL; - } - } - - - _loadInProgress = true; - _indicatorDisplay = true; - _indicatorProgress = 0; - CBPersistMgr *pm = new CBPersistMgr(_gameRef); - _debugAbsolutePathWarning = false; - if (DID_FAIL(ret = pm->initLoad(filename))) goto load_finish; - - //if(DID_FAIL(ret = cleanup())) goto load_finish; - if (DID_FAIL(ret = CSysClassRegistry::getInstance()->loadTable(_gameRef, pm))) goto load_finish; - if (DID_FAIL(ret = CSysClassRegistry::getInstance()->loadInstances(_gameRef, pm))) goto load_finish; - - // data initialization after load - initAfterLoad(); - - _gameRef->applyEvent("AfterLoad", true); - - displayContent(true, false); - //_renderer->flip(); - - getDebugMgr()->onGameInit(); - -load_finish: - _debugAbsolutePathWarning = true; - - _indicatorDisplay = false; - delete pm; - _loadInProgress = false; - - delete _saveLoadImage; - _saveLoadImage = NULL; - - //_gameRef->LOG(0, "Load end %d", CBUtils::GetUsedMemMB()); - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::initAfterLoad() { - CSysClassRegistry::getInstance()->enumInstances(afterLoadRegion, "CBRegion", NULL); - CSysClassRegistry::getInstance()->enumInstances(afterLoadSubFrame, "CBSubFrame", NULL); - CSysClassRegistry::getInstance()->enumInstances(afterLoadSound, "CBSound", NULL); - CSysClassRegistry::getInstance()->enumInstances(afterLoadFont, "CBFontTT", NULL); - CSysClassRegistry::getInstance()->enumInstances(afterLoadScript, "CScScript", NULL); - - _scEngine->refreshScriptBreakpoints(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CBGame::afterLoadRegion(void *region, void *data) { - ((CBRegion *)region)->createRegion(); -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::afterLoadSubFrame(void *subframe, void *data) { - ((CBSubFrame *)subframe)->setSurfaceSimple(); -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::afterLoadSound(void *sound, void *data) { - ((CBSound *)sound)->setSoundSimple(); -} - -////////////////////////////////////////////////////////////////////////// -void CBGame::afterLoadFont(void *font, void *data) { - ((CBFont *)font)->afterLoad(); -} - -////////////////////////////////////////////////////////////////////////// -void CBGame::afterLoadScript(void *script, void *data) { - ((CScScript *)script)->afterLoad(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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.getSize() - 1; i >= 0; i--) { - if (_windows[i]->_visible && !_windows[i]->_disable) { - _focusedWindow = _windows[i]; - break; - } - } - } - - // display all windows - for (int i = 0; i < _windows.getSize(); i++) { - if (_windows[i]->_visible && _windows[i]->_inGame == inGame) { - - res = _windows[i]->display(); - if (DID_FAIL(res)) return res; - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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 CBSound(_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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 = _gameRef->_fileManager->readWholeFile(filename); - if (origBuffer == NULL) { - _gameRef->LOG(0, "CBGame::LoadSettings failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret = STATUS_OK; - - byte *buffer = origBuffer; - byte *params; - int cmd; - CBParser parser(_gameRef); - - 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: - _registry->setBasePath((char *)params); - break; - - case TOKEN_RICH_SAVED_GAMES: - parser.scanStr((char *)params, "%b", &_richSavedGames); - break; - - case TOKEN_SAVED_GAME_EXT: - CBUtils::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 = _registry->readBool("Debug", "AllowWindowed", _settingsAllowWindowed); - _compressedSavegames = _registry->readBool("Debug", "CompressedSavegames", _compressedSavegames); - //_compressedSavegames = false; - - delete [] origBuffer; - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::persist(CBPersistMgr *persistMgr) { - if (!persistMgr->_saving) - cleanup(); - - CBObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_activeObject)); - persistMgr->transfer(TMEMBER(_capturedObject)); - persistMgr->transfer(TMEMBER(_cursorNoninteractive)); - persistMgr->transfer(TMEMBER(_doNotExpandStrings)); - 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)); - - persistMgr->transfer(TMEMBER(_loadImageName)); - persistMgr->transfer(TMEMBER(_saveImageName)); - persistMgr->transfer(TMEMBER(_saveImageX)); - persistMgr->transfer(TMEMBER(_saveImageY)); - persistMgr->transfer(TMEMBER(_loadImageX)); - persistMgr->transfer(TMEMBER(_loadImageY)); - - 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->_saving) - _quitting = false; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::focusWindow(CUIWindow *Window) { - CUIWindow *Prev = _focusedWindow; - - for (int i = 0; i < _windows.getSize(); i++) { - if (_windows[i] == Window) { - if (i < _windows.getSize() - 1) { - _windows.removeAt(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 CBGame::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 CBGame::unfreeze() { - if (_freezeLevel == 0) return STATUS_OK; - - _freezeLevel--; - if (_freezeLevel == 0) { - _state = _origState; - _interactive = _origInteractive; - _scEngine->resumeAll(); - _soundMgr->resumeAll(); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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; - } - - if (event->type == Common::EVENT_KEYDOWN && event->kbd.keycode == Common::KEYCODE_RETURN && (event->kbd.flags == Common::KBD_ALT)) { - // TODO: Handle alt-enter as well as alt-return. - _renderer->switchFullscreen(); - 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; - } //else return true; - - return false; -} - -void CBGame::handleKeyRelease(Common::Event *event) { - _keyboardState->handleKeyRelease(event); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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 CBGame::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 CBGame::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("CBGame::SetWindowTitle -Ignoring textencoding"); - utf8Title = Utf8String(title); - /* WideString wstr = StringUtil::AnsiToWide(Title); - title = StringUtil::WideToUtf8(wstr);*/ - } -#if 0 - CBRenderOSystem *renderer = static_cast(_renderer); - // TODO - - SDL_SetWindowTitle(renderer->GetSdlWindow(), title.c_str()); -#endif - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::getSaveSlotFilename(int slot, char *buffer) { - AnsiString dataDir = getDataDir(); - //sprintf(Buffer, "%s/save%03d.%s", dataDir.c_str(), Slot, _savedGameExt); - CBPersistMgr *pm = new CBPersistMgr(_gameRef); - Common::String filename = pm->getFilenameForSlot(slot); - delete pm; - strcpy(buffer, filename.c_str()); - debugC(kWinterMuteDebugSaveGame, "getSaveSlotFileName(%d) = %s", slot, buffer); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString CBGame::getDataDir() { - AnsiString userDir = PathUtil::getUserDirectory(); - AnsiString baseDir = _registry->getBasePath(); - return PathUtil::combine(userDir, baseDir); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::getSaveSlotDescription(int slot, char *buffer) { - buffer[0] = '\0'; - - char filename[MAX_PATH_LENGTH + 1]; - getSaveSlotFilename(slot, filename); - CBPersistMgr *pm = new CBPersistMgr(_gameRef); - if (!pm) return STATUS_FAILED; - - _debugAbsolutePathWarning = false; - if (DID_FAIL(pm->initLoad(filename))) { - _debugAbsolutePathWarning = true; - delete pm; - return STATUS_FAILED; - } - - _debugAbsolutePathWarning = true; - strcpy(buffer, pm->_savedDescription); - delete pm; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::isSaveSlotUsed(int slot) { - char filename[MAX_PATH_LENGTH + 1]; - getSaveSlotFilename(slot, filename); - - warning("CBGame::IsSaveSlotUsed(%d) - FIXME, ugly solution", slot); - Common::SeekableReadStream *File = g_wintermute->getSaveFileMan()->openForLoading(filename); - if (!File) return false; - delete File; - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::emptySaveSlot(int slot) { - char filename[MAX_PATH_LENGTH + 1]; - getSaveSlotFilename(slot, filename); - CBPersistMgr *pm = new CBPersistMgr(this); - g_wintermute->getSaveFileMan()->removeSavefile(pm->getFilenameForSlot(slot)); - delete pm; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::setActiveObject(CBObject *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 CBGame::pushViewport(CBViewport *viewport) { - _viewportSP++; - if (_viewportSP >= _viewportStack.getSize()) _viewportStack.add(viewport); - else _viewportStack[_viewportSP] = viewport; - - _renderer->setViewport(viewport->getRect()); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::popViewport() { - _viewportSP--; - if (_viewportSP < -1) _gameRef->LOG(0, "Fatal: Viewport stack underflow!"); - - if (_viewportSP >= 0 && _viewportSP < _viewportStack.getSize()) _renderer->setViewport(_viewportStack[_viewportSP]->getRect()); - else _renderer->setViewport(_renderer->_drawOffsetX, - _renderer->_drawOffsetY, - _renderer->_width + _renderer->_drawOffsetX, - _renderer->_height + _renderer->_drawOffsetY); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::getCurrentViewportRect(Rect32 *rect, bool *custom) { - if (rect == NULL) return STATUS_FAILED; - else { - if (_viewportSP >= 0) { - CBPlatform::copyRect(rect, _viewportStack[_viewportSP]->getRect()); - if (custom) *custom = true; - } else { - CBPlatform::setRect(rect, _renderer->_drawOffsetX, - _renderer->_drawOffsetY, - _renderer->_width + _renderer->_drawOffsetX, - _renderer->_height + _renderer->_drawOffsetY); - if (custom) *custom = false; - } - - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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 CBGame::windowLoadHook(CUIWindow *win, char **buf, char **params) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::setInteractive(bool state) { - _interactive = state; - if (_transMgr) _transMgr->_origInteractive = state; -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::resetMousePos() { - Common::Point p; - p.x = _mousePos.x + _renderer->_drawOffsetX; - p.y = _mousePos.y + _renderer->_drawOffsetY; - - CBPlatform::setCursorPos(p.x, p.y); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::displayContent(bool doUpdate, bool displayAll) { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::displayContentSimple() { - // fill black - _renderer->fill(0, 0, 0); - if (_indicatorDisplay) displayIndicator(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::displayIndicator() { - if (_saveLoadImage) { - Rect32 rc; - CBPlatform::setRect(&rc, 0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight()); - if (_loadInProgress) _saveLoadImage->displayTrans(_loadImageX, _loadImageY, rc); - else _saveLoadImage->displayTrans(_saveImageX, _saveImageY, rc); - } - - if ((!_indicatorDisplay && _indicatorWidth <= 0) || _indicatorHeight <= 0) return STATUS_OK; - _renderer->setupLines(); - for (int i = 0; i < _indicatorHeight; i++) - _renderer->drawLine(_indicatorX, _indicatorY + i, _indicatorX + (int)(_indicatorWidth * (float)((float)_indicatorProgress / 100.0f)), _indicatorY + i, _indicatorColor); - - _renderer->setup2D(); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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 - CBSound *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 CBGame::resetContent() { - _scEngine->clearGlobals(); - //_timer = 0; - //_liveTimer = 0; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CBGame::DEBUG_DumpClassRegistry() { - warning("DEBUG_DumpClassRegistry - untested"); - Common::DumpFile *f = new Common::DumpFile; - f->open("zz_class_reg_dump.log"); - - CSysClassRegistry::getInstance()->dumpClasses(f); - - f->close(); - delete f; - _gameRef->quickMessage("Classes dump completed."); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::invalidateDeviceObjects() { - for (int i = 0; i < _regObjects.getSize(); i++) { - _regObjects[i]->invalidateDeviceObjects(); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::restoreDeviceObjects() { - for (int i = 0; i < _regObjects.getSize(); i++) { - _regObjects[i]->restoreDeviceObjects(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::setWaitCursor(const char *filename) { - delete _cursorNoninteractive; - _cursorNoninteractive = NULL; - - _cursorNoninteractive = new CBSprite(_gameRef); - if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile(filename))) { - delete _cursorNoninteractive; - _cursorNoninteractive = NULL; - return STATUS_FAILED; - } else return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::isVideoPlaying() { - if (_videoPlayer->isPlaying()) return true; - if (_theoraPlayer && _theoraPlayer->isPlaying()) return true; - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::stopVideo() { - if (_videoPlayer->isPlaying()) _videoPlayer->stop(); - if (_theoraPlayer && _theoraPlayer->isPlaying()) { - _theoraPlayer->stop(); - delete _theoraPlayer; - _theoraPlayer = NULL; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBGame::drawCursor(CBSprite *cursor) { - if (!cursor) return STATUS_FAILED; - if (cursor != _lastCursor) { - cursor->reset(); - _lastCursor = cursor; - } - return cursor->draw(_mousePos.x, _mousePos.y); -} - - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -bool CBGame::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 CBGame::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; - CBPlatform::setCapture(/*_renderer->_window*/); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::onMouseLeftUp() { - if (_activeObject) _activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT); - - CBPlatform::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::onPaint() { - if (_renderer && _renderer->_windowed && _renderer->_ready) { - _renderer->initLoop(); - displayContent(false, true); - displayDebugInfo(); - _renderer->windowedBlt(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::onWindowClose() { - if (canHandleEvent("QuitGame")) { - if (_state != GAME_FROZEN) _gameRef->applyEvent("QuitGame"); - return STATUS_OK; - } else return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::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()); - 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((byte *)_activeObject->_name, 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; -} - -////////////////////////////////////////////////////////////////////////// -CBDebugger *CBGame::getDebugMgr() { - if (!_debugMgr) _debugMgr = new CBDebugger(this); - return _debugMgr; -} - - -////////////////////////////////////////////////////////////////////////// -void CBGame::getMousePos(Point32 *pos) { - CBPlatform::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 (!CBPlatform::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; - - CBPlatform::setCursorPos(newPos.x, newPos.y); - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::miniUpdate() { - if (!_miniUpdateEnabled) return STATUS_OK; - - if (CBPlatform::getTime() - _lastMiniUpdate > 200) { - if (_soundMgr) _soundMgr->initLoop(); - _lastMiniUpdate = CBPlatform::getTime(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::onScriptShutdown(CScScript *script) { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::isLeftDoubleClick() { - return isDoubleClick(0); -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::isRightDoubleClick() { - return isDoubleClick(1); -} - -////////////////////////////////////////////////////////////////////////// -bool CBGame::isDoubleClick(int buttonIndex) { - uint32 maxDoubleCLickTime = 500; - int maxMoveX = 4; - int maxMoveY = 4; - - Point32 pos; - CBPlatform::getCursorPos(&pos); - - int moveX = abs(pos.x - _lastClick[buttonIndex].posX); - int moveY = abs(pos.y - _lastClick[buttonIndex].posY); - - - if (_lastClick[buttonIndex].time == 0 || CBPlatform::getTime() - _lastClick[buttonIndex].time > maxDoubleCLickTime || moveX > maxMoveX || moveY > maxMoveY) { - _lastClick[buttonIndex].time = CBPlatform::getTime(); - _lastClick[buttonIndex].posX = pos.x; - _lastClick[buttonIndex].posY = pos.y; - return false; - } else { - _lastClick[buttonIndex].time = 0; - return true; - } -} - -////////////////////////////////////////////////////////////////////////// -void CBGame::autoSaveOnExit() { - _soundMgr->saveSettings(); - _registry->saveValues(); - - if (!_autoSaveOnExit) return; - if (_state == GAME_FROZEN) return; - - SaveGame(_autoSaveSlot, "autosave", true); -} - -////////////////////////////////////////////////////////////////////////// -void CBGame::addMem(int bytes) { - _usedMem += bytes; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString CBGame::getDeviceType() const { - return "computer"; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BGame.h b/engines/wintermute/base/BGame.h deleted file mode 100644 index 7441d81b07..0000000000 --- a/engines/wintermute/base/BGame.h +++ /dev/null @@ -1,391 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BGAME_H -#define WINTERMUTE_BGAME_H - -#include "engines/wintermute/base/BDebugger.h" -#include "engines/wintermute/base/gfx/base_renderer.h" -#include "engines/wintermute/base/BObject.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 CBSoundMgr; -class CBFader; -class CBFont; -class CBFileManager; -class CBTransitionMgr; -class CScEngine; -class CBFontStorage; -class CBStringTable; -class CBQuickMsg; -class CUIWindow; -class CBViewport; -class CBRenderer; -class CBRegistry; -class CBSaveThumbHelper; -class CBSurfaceStorage; -class CSXMath; -class CBKeyboardState; -class CVidPlayer; -class CVidTheoraPlayer; - -#define NUM_MUSIC_CHANNELS 5 - -class CBGame: public CBObject { -public: - DECLARE_PERSISTENT(CBGame, CBObject) - - virtual bool onScriptShutdown(CScScript *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 bool miniUpdate(); - - void getMousePos(Point32 *Pos); - Rect32 _mouseLockRect; - - bool _shuttingDown; - - virtual bool displayDebugInfo(); - bool _debugShowFPS; - - bool _suspendedRendering; - int _soundBufferSizeSec; - - TTextEncoding _textEncoding; - bool _textRTL; - - CBSprite *_loadingIcon; - int _loadingIconX; - int _loadingIconY; - int _loadingIconPersistent; - - virtual bool resetContent(); - - void DEBUG_DumpClassRegistry(); - bool setWaitCursor(const char *filename); - char *_localSaveDir; - bool _saveDirChecked; - - int _indicatorProgress; -protected: - bool _indicatorDisplay; - uint32 _indicatorColor; - int _indicatorX; - int _indicatorY; - int _indicatorWidth; - int _indicatorHeight; - - bool _richSavedGames; - char *_savedGameExt; - - char *_loadImageName; - char *_saveImageName; - int _saveImageX; - int _saveImageY; - int _loadImageX; - int _loadImageY; - - CBSurface *_saveLoadImage; - bool displayIndicator(); - - bool _reportTextureFormat; -public: - int _thumbnailWidth; - int _thumbnailHeight; - - void setEngineLogCallback(ENGINE_LOG_CALLBACK callback = NULL, void *data = NULL); - ENGINE_LOG_CALLBACK _engineLogCallback; - void *_engineLogCallbackData; - bool _editorMode; - - bool _doNotExpandStrings; - void getOffset(int *offsetX, int *offsetY); - void setOffset(int offsetX, int offsetY); - int getSequence(); - int _offsetY; - int _offsetX; - float _offsetPercentX; - float _offsetPercentY; - CBObject *_mainObject; - - bool initInput(); - bool initLoop(); - uint32 _currentTime; - uint32 _deltaTime; - CBFont *_systemFont; - CBFont *_videoFont; - bool initialize1(); - bool initialize2(); - bool initialize3(); - CBFileManager *_fileManager; - CBTransitionMgr *_transMgr; - CBDebugger *getDebugMgr(); - - void LOG(bool res, const char *fmt, ...); - - CBRenderer *_renderer; - CBSoundMgr *_soundMgr; - CScEngine *_scEngine; - CSXMath *_mathClass; - CBSurfaceStorage *_surfaceStorage; - CBFontStorage *_fontStorage; - CBGame(); - - virtual ~CBGame(); - void DEBUG_DebugDisable(); - void DEBUG_DebugEnable(const char *filename = NULL); - bool _debugDebugMode; - bool _debugAbsolutePathWarning; - - void *_debugLogFile; - int _sequence; - virtual bool loadFile(const char *filename); - virtual bool loadBuffer(byte *buffer, bool complete = true); - CBArray _quickMessages; - CBArray _windows; - CBArray _viewportStack; - - int _viewportSP; - - CBStringTable *_stringTable; - int _settingsResWidth; - int _settingsResHeight; - char *_settingsGameFile; - bool _suppressScriptErrors; - bool _mouseLeftDown; -protected: - bool _mouseRightDown; - bool _mouseMidlleDown; - bool _settingsRequireAcceleration; - bool _settingsAllowWindowed; - bool _settingsAllowAdvanced; - bool _settingsAllowAccessTab; - bool _settingsAllowAboutTab; - bool _settingsRequireSound; - bool _settingsAllowDesktopRes; - int _settingsTLMode; - CBFader *_fader; - virtual bool invalidateDeviceObjects(); - virtual bool restoreDeviceObjects(); -public: - virtual bool ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name); - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - // compatibility bits - bool _compatKillMethodThreads; - -private: - // FPS stuff - uint32 _lastTime; - uint32 _fpsTime; - uint32 _framesRendered; - Common::String _gameId; -public: - const char* getGameId() { return _gameId.c_str(); } - void setGameId(const Common::String& gameId) { _gameId = gameId; } - uint32 _surfaceGCCycleTime; - bool _smartCache; - bool _videoSubtitles; - bool _subtitles; - uint32 _musicStartTime[NUM_MUSIC_CHANNELS]; - bool _compressedSavegames; - int _scheduledLoadSlot; - bool _loading; - bool _personalizedSave; - bool emptySaveSlot(int slot); - bool isSaveSlotUsed(int slot); - bool getSaveSlotDescription(int slot, char *buffer); - bool getSaveSlotFilename(int slot, char *buffer); - void setWindowTitle(); - 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); -protected: - int _freezeLevel; -public: - bool unfreeze(); - bool freeze(bool includingMusic = true); - bool focusWindow(CUIWindow *window); - CVidPlayer *_videoPlayer; - CVidTheoraPlayer *_theoraPlayer; - bool _loadInProgress; - CUIWindow *_focusedWindow; - bool _editorForceScripts; -protected: - static void afterLoadRegion(void *region, void *data); - static void afterLoadSubFrame(void *subframe, void *data); - static void afterLoadSound(void *sound, void *data); - static void afterLoadFont(void *font, void *data); - static void afterLoadScript(void *script, void *data); -public: - static void invalidateValues(void *value, void *data); - - bool loadSettings(const char *filename); - 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); - CBSound *_music[NUM_MUSIC_CHANNELS]; - bool _musicCrossfadeRunning; - bool _musicCrossfadeSwap; - uint32 _musicCrossfadeStartTime; - uint32 _musicCrossfadeLength; - int _musicCrossfadeChannel1; - int _musicCrossfadeChannel2; - bool displayWindows(bool inGame = false); - CBRegistry *_registry; - bool _useD3D; - virtual bool cleanup(); - virtual bool loadGame(int slot); - virtual bool loadGame(const char *filename); - virtual bool SaveGame(int slot, const char *desc, bool quickSave = false); - virtual bool showCursor(); - - CBSprite *_cursorNoninteractive; - CBObject *_activeObject; - CBKeyboardState *_keyboardState; - bool _interactive; - TGameState _state; - TGameState _origState; - bool _origInteractive; - uint32 _timer; - uint32 _timerDelta; - uint32 _timerLast; - - uint32 _liveTimer; - uint32 _liveTimerDelta; - uint32 _liveTimerLast; - - CBObject *_capturedObject; - Point32 _mousePos; - bool validObject(CBObject *object); - bool unregisterObject(CBObject *object); - bool registerObject(CBObject *object); - void quickMessage(const char *text); - void quickMessageForm(char *fmt, ...); - bool displayQuickMsg(); - uint32 _fps; - bool updateMusicCrossfade(); - - bool isVideoPlaying(); - bool stopVideo(); - - CBArray _regObjects; -public: - 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(CUIWindow *win, char **buf, char **params); - virtual bool windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name); - bool getCurrentViewportOffset(int *offsetX = NULL, int *offsetY = NULL); - bool getCurrentViewportRect(Rect32 *rect, bool *custom = NULL); - bool popViewport(); - bool pushViewport(CBViewport *Viewport); - bool setActiveObject(CBObject *Obj); - CBSprite *_lastCursor; - bool drawCursor(CBSprite *Cursor); - - virtual bool initAfterLoad(); - CBSaveThumbHelper *_cachedThumbnail; - AnsiString getDataDir(); - void addMem(int bytes); - - bool _touchInterface; - bool _constrainedMemory; - AnsiString getDeviceType() const; - -private: - CBDebugger *_debugMgr; - - 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/BKeyboardState.cpp b/engines/wintermute/base/BKeyboardState.cpp deleted file mode 100644 index 85ab15f58e..0000000000 --- a/engines/wintermute/base/BKeyboardState.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BKeyboardState.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "common/system.h" -#include "common/keyboard.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBKeyboardState, false) - -////////////////////////////////////////////////////////////////////////// -CBKeyboardState::CBKeyboardState(CBGame *inGame): CBScriptable(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; - } -} - -////////////////////////////////////////////////////////////////////////// -CBKeyboardState::~CBKeyboardState() { - delete[] _keyStates; -} - -void CBKeyboardState::handleKeyPress(Common::Event *event) { - if (event->type == Common::EVENT_KEYDOWN) { - _keyStates[event->kbd.keycode] = true; - } -} - -void CBKeyboardState::handleKeyRelease(Common::Event *event) { - if (event->type == Common::EVENT_KEYUP) { - _keyStates[event->kbd.keycode] = false; - } -} - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CBKeyboardState::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // IsKeyDown - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "IsKeyDown") == 0) { - stack->correctParams(1); - CScValue *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(); - - warning("BKeyboardState doesnt yet have state-support %d", vKey); //TODO; -// Uint8 *state = SDL_GetKeyboardState(NULL); -// SDL_Scancode scanCode = SDL_GetScancodeFromKey(VKeyToKeyCode(vKey)); - bool isDown = _keyStates[vKeyToKeyCode(vKey)]; - - stack->pushBool(isDown); - return STATUS_OK; - } - - else return CBScriptable::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBKeyboardState::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 CBScriptable::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBKeyboardState::scSetProperty(const char *name, CScValue *value) { - /* - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - if (_renderer) SetWindowText(_renderer->_window, _name); - return STATUS_OK; - } - - else*/ return CBScriptable::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBKeyboardState::scToString() { - return "[keyboard state]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBKeyboardState::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)) { - _currentPrintable = true; - } else { - _currentPrintable = false; - } - //_currentKeyData = KeyData; - - _currentControl = isControlDown(); - _currentAlt = isAltDown(); - _currentShift = isShiftDown(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBKeyboardState::persist(CBPersistMgr *persistMgr) { - //if(!persistMgr->_saving) cleanup(); - CBScriptable::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->_saving) { - _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 CBKeyboardState::isShiftDown() { - int mod = g_system->getEventManager()->getModifierState(); - return (mod & Common::KBD_SHIFT); -} - -////////////////////////////////////////////////////////////////////////// -bool CBKeyboardState::isControlDown() { - int mod = g_system->getEventManager()->getModifierState(); - return (mod & Common::KBD_CTRL); -} - -////////////////////////////////////////////////////////////////////////// -bool CBKeyboardState::isAltDown() { - int mod = g_system->getEventManager()->getModifierState(); - return (mod & Common::KBD_ALT); -} - -////////////////////////////////////////////////////////////////////////// -uint32 CBKeyboardState::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 { - VK_SPACE = 32, - VK_LEFT = 37, - VK_UP = 38, - VK_RIGHT = 39, - VK_DOWN = 40 -}; - -////////////////////////////////////////////////////////////////////////// -Common::KeyCode CBKeyboardState::vKeyToKeyCode(uint32 vkey) { - // todo - switch (vkey) { - case VK_SPACE: - return Common::KEYCODE_SPACE; - break; - case VK_LEFT: - return Common::KEYCODE_LEFT; - break; - case VK_RIGHT: - return Common::KEYCODE_RIGHT; - break; - case VK_UP: - return Common::KEYCODE_UP; - break; - case VK_DOWN: - 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/BKeyboardState.h b/engines/wintermute/base/BKeyboardState.h deleted file mode 100644 index e3a4a903f7..0000000000 --- a/engines/wintermute/base/BKeyboardState.h +++ /dev/null @@ -1,75 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BKEYBOARD_STATE_H -#define WINTERMUTE_BKEYBOARD_STATE_H - - -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/base/BScriptable.h" -#include "common/keyboard.h" -#include "common/events.h" - -namespace WinterMute { - -class CBKeyboardState : public CBScriptable { -public: - uint32 _currentKeyData; - uint32 _currentCharCode; - bool _currentPrintable; - - bool _currentShift; - bool _currentAlt; - bool _currentControl; - - DECLARE_PERSISTENT(CBKeyboardState, CBScriptable) - CBKeyboardState(CBGame *inGame); - virtual ~CBKeyboardState(); - 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 CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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/BNamedObject.cpp b/engines/wintermute/base/BNamedObject.cpp deleted file mode 100644 index 9587da45e8..0000000000 --- a/engines/wintermute/base/BNamedObject.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BNamedObject.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBNamedObject::CBNamedObject(CBGame *inGame) : CBBase(inGame) { - _name = NULL; -} - -////////////////////////////////////////////////////////////////////////// -CBNamedObject::CBNamedObject() : CBBase() { - _name = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CBNamedObject::CBNamedObject(TDynamicConstructor, TDynamicConstructor) { - _name = NULL; -} - -////////////////////////////////////////////////////////////////////////// -CBNamedObject::~CBNamedObject(void) { - delete[] _name; - _name = NULL; -} - - -////////////////////////////////////////////////////////////////////// -void CBNamedObject::setName(const char *name) { - delete[] _name; - - _name = new char [strlen(name) + 1]; - if (_name != NULL) strcpy(_name, name); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BNamedObject.h b/engines/wintermute/base/BNamedObject.h deleted file mode 100644 index 4d5fdb0c0e..0000000000 --- a/engines/wintermute/base/BNamedObject.h +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BNAMEDOBJECT_H -#define WINTERMUTE_BNAMEDOBJECT_H - - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBNamedObject : public CBBase { -public: - CBNamedObject(CBGame *inGame); - CBNamedObject(); - virtual ~CBNamedObject(void); - CBNamedObject(TDynamicConstructor, TDynamicConstructor); - - char *_name; - void setName(const char *name); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BObject.cpp b/engines/wintermute/base/BObject.cpp deleted file mode 100644 index ed5d6fa5b7..0000000000 --- a/engines/wintermute/base/BObject.cpp +++ /dev/null @@ -1,1128 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BObject.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBObject, false) - -////////////////////////////////////////////////////////////////////// -CBObject::CBObject(CBGame *inGame): CBScriptHolder(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(); - - CBPlatform::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; -} - - -////////////////////////////////////////////////////////////////////// -CBObject::~CBObject() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::cleanup() { - if (_gameRef && _gameRef->_activeObject == this) - _gameRef->_activeObject = NULL; - - CBScriptHolder::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 CBObject::setCaption(const char *caption, int caseVal) { // TODO: rename Case to something usefull - 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 *CBObject::getCaption(int caseVal) { - if (caseVal == 0) caseVal = 1; - if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == NULL) - return ""; - else return _caption[caseVal - 1]; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::listen(CBScriptHolder *param1, uint32 param2) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CBObject::scCallMethod(CScScript *script, CScStack *stack, CScStack *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->_filename) stack->pushNULL(); - else stack->pushString(_cursor->_filename); - - 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; - - CScValue *val1 = stack->pop(); - CScValue *val2 = stack->pop(); - CScValue *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; - - CScValue *val1 = stack->pop(); - CScValue *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 CBScriptHolder::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBObject::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 CBScriptHolder::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::scSetProperty(const char *name, CScValue *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 CBScriptHolder::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBObject::scToString() { - return "[object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::showCursor() { - if (_cursor) return _gameRef->drawCursor(_cursor); - else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::saveAsText(CBDynBuffer *buffer, int indent) { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::persist(CBPersistMgr *persistMgr) { - CBScriptHolder::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 CBObject::setCursor(const char *filename) { - if (!_sharedCursors) { - delete _cursor; - _cursor = NULL; - } - - _sharedCursors = false; - _cursor = new CBSprite(_gameRef); - if (!_cursor || DID_FAIL(_cursor->loadFile(filename))) { - delete _cursor; - _cursor = NULL; - return STATUS_FAILED; - } else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::setActiveCursor(const char *filename) { - delete _activeCursor; - _activeCursor = new CBSprite(_gameRef); - if (!_activeCursor || DID_FAIL(_activeCursor->loadFile(filename))) { - delete _activeCursor; - _activeCursor = NULL; - return STATUS_FAILED; - } else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CBObject::getHeight() { - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::handleMouse(TMouseEvent event, TMouseButton button) { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::handleKeypress(Common::Event *event, bool printable) { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::handleMouseWheel(int delta) { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::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 CBSound(_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 CBObject::stopSFX(bool deleteSound) { - if (_sFX) { - _sFX->stop(); - if (deleteSound) { - delete _sFX; - _sFX = NULL; - } - return STATUS_OK; - } else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::pauseSFX() { - if (_sFX) return _sFX->pause(); - else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::resumeSFX() { - if (_sFX) return _sFX->resume(); - else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::setSFXTime(uint32 time) { - _sFXStart = time; - if (_sFX && _sFX->isPlaying()) return _sFX->setPositionTime(time); - else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::setSFXVolume(int volume) { - _sFXVolume = volume; - if (_sFX) return _sFX->setVolumePercent(volume); - else return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::updateSounds() { - if (_soundEvent) { - if (_sFX && !_sFX->isPlaying()) { - applyEvent(_soundEvent); - setSoundEvent(NULL); - } - } - - if (_sFX) updateOneSound(_sFX); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBObject::updateOneSound(CBSound *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 CBObject::resetSoundPan() { - if (!_sFX) return STATUS_OK; - else { - return _sFX->setPan(0.0f); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::getExtendedFlag(const char *flagName) { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBObject::isReady() { - return _ready; -} - - -////////////////////////////////////////////////////////////////////////// -void CBObject::setSoundEvent(const char *eventName) { - delete[] _soundEvent; - _soundEvent = NULL; - if (eventName) { - _soundEvent = new char[strlen(eventName) + 1]; - if (_soundEvent) strcpy(_soundEvent, eventName); - } -} - -////////////////////////////////////////////////////////////////////////// -bool CBObject::afterMove() { - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BObject.h b/engines/wintermute/base/BObject.h deleted file mode 100644 index c855c770b7..0000000000 --- a/engines/wintermute/base/BObject.h +++ /dev/null @@ -1,144 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BOBJECT_H -#define WINTERMUTE_BOBJECT_H - - -#include "engines/wintermute/base/BScriptHolder.h" -#include "engines/wintermute/persistent.h" -#include "common/events.h" - -namespace WinterMute { - -class CBSprite; -class CBSound; -class CBSurface; -class CBScriptHolder; -class CScValue; -class CScStack; -class CScScript; -class CBObject : public CBScriptHolder { -public: - TSpriteBlendMode _blendMode; - virtual bool afterMove(); - float _relativeRotate; - bool _rotateValid; - float _rotate; - void setSoundEvent(const char *eventName); - bool _rotatable; - uint32 _alphaColor; - float _scale; - float _scaleX; - float _scaleY; - float _relativeScale; - virtual bool isReady(); - virtual bool getExtendedFlag(const char *flagName); - virtual bool resetSoundPan(); - virtual bool updateSounds(); - bool updateOneSound(CBSound *sound); - bool _autoSoundPanning; - uint32 _sFXStart; - int _sFXVolume; - 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); - CBSound *_sFX; - - TSFXType _sFXType; - float _sFXParam1; - float _sFXParam2; - float _sFXParam3; - float _sFXParam4; - - 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 _editorSelected; - bool _editorAlwaysRegister; - bool _editorOnly; - bool _is3D; - DECLARE_PERSISTENT(CBObject, CBScriptHolder) - virtual bool showCursor(); - CBSprite *_cursor; - bool _sharedCursors; - CBSprite *_activeCursor; - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - virtual bool listen(CBScriptHolder *param1, uint32 param2); - bool _ready; - bool _registrable; - bool _zoomable; - bool _shadowable; - Rect32 _rect; - bool _rectSet; - int _iD; - bool _movable; - CBObject(CBGame *inGame); - virtual ~CBObject(); - char *_caption[7]; - char *_soundEvent; - int _posY; - int _posX; - bool _saveState; - - // 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 CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BParser.cpp b/engines/wintermute/base/BParser.cpp deleted file mode 100644 index 80d3b58213..0000000000 --- a/engines/wintermute/base/BParser.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BParser.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" -#include "common/util.h" - -#define WHITESPACE " \t\n\r" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////// -CBParser::CBParser(CBGame *inGame): CBBase(inGame) { - _whiteSpace = new char [strlen(WHITESPACE) + 1]; - strcpy(_whiteSpace, WHITESPACE); -} - - -////////////////////////////////////////////////////////////////////// -CBParser::~CBParser() { - if (_whiteSpace != NULL) delete [] _whiteSpace; -} - - -////////////////////////////////////////////////////////////////////// -char *CBParser::getLastOffender() { - return _lastOffender; -} - - -////////////////////////////////////////////////////////////////////// -int32 CBParser::getObject(char **buf, 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. - // 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 CBParser::getCommand(char **buf, TokenDesc *tokens, char **params) { - if (!*buf) return PARSERR_TOKENNOTFOUND; - _gameRef->miniUpdate(); - char *name; - return getObject(buf, tokens, &name, params); -} - - -////////////////////////////////////////////////////////////////////// -void CBParser::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 *CBParser::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 *CBParser::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; -} - - -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// -char *CBParser::getToken(char **buf) { - static char token[100]; - 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 CBParser::getTokenFloat(char **buf) { - char *t = getToken(buf); - 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 CBParser::getTokenInt(char **buf) { - char *t = getToken(buf); - if (!((*t >= '0' && *t <= '9') || *t == '-')) { - // Error situation. We handle this by return 0. - return 0; - } - int rc = atoi(t); - return rc; -} - - -////////////////////////////////////////////////////////////////////// -void CBParser::skipToken(char **buf, char *tok, char * /*msg*/) { - char *t = getToken(buf); - if (strcmp(t, tok)) return; // Error -} - - -////////////////////////////////////////////////////////////////////// -int CBParser::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) { - strncpy(a, in, (int)(in2 - in)); - a[(int)(in2 - in)] = 0; - in = in2 + 1; - } else { - strcpy(a, in); - in = strchr(in, 0); - } - } else { - const char *in2 = in + strspn(in, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789."); - strncpy(a, in, (int)(in2 - in)); - a[(int)(in2 - in)] = 0; - 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/BParser.h b/engines/wintermute/base/BParser.h deleted file mode 100644 index ae886953a9..0000000000 --- a/engines/wintermute/base/BParser.h +++ /dev/null @@ -1,89 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BPARSER_H -#define WINTERMUTE_BPARSER_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 CBParser::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/base/BBase.h" -#include "engines/wintermute/coll_templ.h" - -namespace WinterMute { - -class CBParser : public CBBase { -public: - struct TokenDesc { - int32 id; - const char *token; - }; - -public: - int scanStr(const char *in, const char *format, ...); - int32 getCommand(char **buf, TokenDesc *tokens, char **params); - CBParser(CBGame *inGame = NULL); - virtual ~CBParser(); -private: - char *getLastOffender(); - void skipToken(char **buf, char *tok, char *msg = NULL); - int getTokenInt(char **buf); - float getTokenFloat(char **buf); - char *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, TokenDesc *tokens, char **name, char **data); - int _parserLine; - char _lastOffender[255]; - char *_whiteSpace; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BPersistMgr.cpp b/engines/wintermute/base/BPersistMgr.cpp deleted file mode 100644 index f8faced95f..0000000000 --- a/engines/wintermute/base/BPersistMgr.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFileManager.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BPersistMgr.h" -#include "engines/wintermute/base/BSaveThumbHelper.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/math/Vector2.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/base/BSound.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 - -////////////////////////////////////////////////////////////////////////// -CBPersistMgr::CBPersistMgr(CBGame *inGame, const char *savePrefix): CBBase(inGame) { - _saving = false; -// _buffer = NULL; -// _bufferSize = 0; - _offset = 0; - _saveStream = NULL; - _loadStream = 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"; - } -} - - -////////////////////////////////////////////////////////////////////////// -CBPersistMgr::~CBPersistMgr() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::getSaveStateDesc(int slot, SaveStateDescriptor &desc) { - Common::String filename = getFilenameForSlot(slot); - warning("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 CBPersistMgr::deleteSaveSlot(int slot) { - Common::String filename = getFilenameForSlot(slot); - g_system->getSavefileManager()->removeSavefile(filename); -} - -uint32 CBPersistMgr::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 CBPersistMgr::getSaveExists(int slot) { - Common::String filename = getFilenameForSlot(slot); - warning("Trying to list savegame %s in slot %d", filename.c_str(), slot); - if (DID_FAIL(readHeader(filename))) { - return false; - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CBPersistMgr::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 CBSaveThumbHelper(_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->_name); - - // 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 CBPersistMgr::readHeader(const Common::String &filename) { - cleanup(); - - _saving = false; - - _loadStream = g_system->getSavefileManager()->openForLoading(filename); - //_buffer = _gameRef->_fileManager->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 CBPersistMgr::initLoad(const char *filename) { - if (DID_FAIL(readHeader(filename))) { - cleanup(); - return STATUS_FAILED; - } - _saving = false; - - if (_savedName == "" || scumm_stricmp(_savedName.c_str(), _gameRef->_name) != 0) { - _gameRef->LOG(0, "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) - ) { - _gameRef->LOG(0, "ERROR: Saved game version is newer than current game"); - _gameRef->LOG(0, "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) - ) { - _gameRef->LOG(0, "ERROR: Saved game is too old and cannot be used by this version of game engine"); - _gameRef->LOG(0, "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 ( _savedVerMajor != DCGF_VER_MAJOR || _savedVerMinor != DCGF_VER_MINOR) - { - _gameRef->LOG(0, "ERROR: Saved game is created by other WME version"); - goto init_fail; - } - */ - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBPersistMgr::saveFile(const char *filename) { - return _gameRef->_fileManager->saveFile(filename, ((Common::MemoryWriteStreamDynamic *)_saveStream)->getData(), ((Common::MemoryWriteStreamDynamic *)_saveStream)->size(), _gameRef->_compressedSavegames, _richBuffer, _richBufferSize); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBPersistMgr::putBytes(byte *buffer, uint32 size) { - _saveStream->write(buffer, size); - if (_saveStream->err()) - return STATUS_FAILED; - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBPersistMgr::getBytes(byte *buffer, uint32 size) { - _loadStream->read(buffer, size); - if (_loadStream->err()) - return STATUS_FAILED; - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CBPersistMgr::putDWORD(uint32 val) { - _saveStream->writeUint32LE(val); -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CBPersistMgr::getDWORD() { - uint32 ret = _loadStream->readUint32LE(); - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -void CBPersistMgr::putString(const Common::String &val) { - if (!val.size()) putString("(null)"); - else { - _saveStream->writeUint32LE(val.size()); - _saveStream->writeString(val); - } -} - -Common::String CBPersistMgr::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 *CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::putFloat(float val) { - Common::String str = Common::String::format("F%f", val); - _saveStream->writeUint32LE(str.size()); - _saveStream->writeString(str); -} - -float CBPersistMgr::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 CBPersistMgr::putDouble(double val) { - Common::String str = Common::String::format("F%f", val); - str.format("D%f", val); - _saveStream->writeUint32LE(str.size()); - _saveStream->writeString(str); -} - -double CBPersistMgr::getDouble() { - char *str = getString(); - double value = 0.0f; - int ret = sscanf(str, "F%f", &value); - if (ret != 1) { - warning("%s not parsed as float", str); - } - delete[] str; - return value; -} - -////////////////////////////////////////////////////////////////////////// -// bool -bool CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::transfer(const char *name, void *val) { - int classID = -1, instanceID = -1; - - if (_saving) { - CSysClassRegistry::getInstance()->getPointerID(*(void **)val, &classID, &instanceID); - if (*(void **)val != NULL && (classID == -1 || instanceID == -1)) { - _gameRef->LOG(0, "Warning: invalid instance '%s'", name); - } - - _saveStream->writeUint32LE(classID); - _saveStream->writeUint32LE(instanceID); - } else { - classID = _loadStream->readUint32LE(); - instanceID = _loadStream->readUint32LE(); - - *(void **)val = CSysClassRegistry::getInstance()->idToPointer(classID, instanceID); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBPersistMgr::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/BPersistMgr.h b/engines/wintermute/base/BPersistMgr.h deleted file mode 100644 index 2e6ee8058c..0000000000 --- a/engines/wintermute/base/BPersistMgr.h +++ /dev/null @@ -1,114 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BPERSISTMGR_H -#define WINTERMUTE_BPERSISTMGR_H - - -#include "engines/wintermute/base/BBase.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 CBPersistMgr : public CBBase { -public: - char *_savedDescription; - TimeDate _savedTimestamp; - uint32 _savedPlayTime; - byte _savedVerMajor; - byte _savedVerMinor; - byte _savedVerBuild; - byte _savedExtMajor; - byte _savedExtMinor; - Common::String _savePrefix; - Common::String _savedName; - bool saveFile(const char *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 char *filename); - bool initSave(const char *desc); - bool getBytes(byte *buffer, uint32 size); - bool putBytes(byte *buffer, uint32 size); - uint32 _offset; - - bool _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); - CBPersistMgr(CBGame *inGame = NULL, const char *savePrefix = NULL); - virtual ~CBPersistMgr(); - bool checkVersion(byte verMajor, byte verMinor, byte verBuild); - - uint32 _thumbnailDataSize; - byte *_thumbnailData; - Common::String getFilenameForSlot(int slot) const; -private: - bool readHeader(const Common::String &filename); - TimeDate getTimeDate(); - bool putTimeDate(const TimeDate &t); - Common::WriteStream *_saveStream; - Common::SeekableReadStream *_loadStream; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BPoint.cpp b/engines/wintermute/base/BPoint.cpp deleted file mode 100644 index 4c80e154f2..0000000000 --- a/engines/wintermute/base/BPoint.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BPoint.h" -#include "engines/wintermute/base/BPersistMgr.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBPoint, false) - -////////////////////////////////////////////////////////////////////////// -CBPoint::CBPoint() { - x = y = 0; -} - - -////////////////////////////////////////////////////////////////////////// -CBPoint::~CBPoint() { - -} - - -////////////////////////////////////////////////////////////////////////// -CBPoint::CBPoint(int initX, int initY) { - x = initX; - y = initY; -} - -////////////////////////////////////////////////////////////////////////// -bool CBPoint::persist(CBPersistMgr *persistMgr) { - - persistMgr->transfer(TMEMBER(x)); - persistMgr->transfer(TMEMBER(y)); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BPoint.h b/engines/wintermute/base/BPoint.h deleted file mode 100644 index 3e4adb5d13..0000000000 --- a/engines/wintermute/base/BPoint.h +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BPOINT_H -#define WINTERMUTE_BPOINT_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBPoint: public CBBase { -public: - DECLARE_PERSISTENT(CBPoint, CBBase) - CBPoint(); - CBPoint(int initX, int initY); - int y; - int x; - virtual ~CBPoint(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BQuickMsg.cpp b/engines/wintermute/base/BQuickMsg.cpp deleted file mode 100644 index 32bd04afe2..0000000000 --- a/engines/wintermute/base/BQuickMsg.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BQuickMsg.h" -#include "engines/wintermute/base/BGame.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBQuickMsg::CBQuickMsg(CBGame *inGame, const char *text): CBBase(inGame) { - _text = new char [strlen(text) + 1]; - if (_text) strcpy(_text, text); - _startTime = _gameRef->_currentTime; -} - - -////////////////////////////////////////////////////////////////////////// -CBQuickMsg::~CBQuickMsg() { - if (_text) delete [] _text; -} - - -////////////////////////////////////////////////////////////////////////// -char *CBQuickMsg::getText() { - return _text; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BQuickMsg.h b/engines/wintermute/base/BQuickMsg.h deleted file mode 100644 index c247183714..0000000000 --- a/engines/wintermute/base/BQuickMsg.h +++ /dev/null @@ -1,48 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BQUICKMSG_H -#define WINTERMUTE_BQUICKMSG_H - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBQuickMsg : public CBBase { -public: - char *getText(); - uint32 _startTime; - char *_text; - CBQuickMsg(CBGame *inGame, const char *Text); - virtual ~CBQuickMsg(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BRegion.cpp b/engines/wintermute/base/BRegion.cpp deleted file mode 100644 index c8ec87e04a..0000000000 --- a/engines/wintermute/base/BRegion.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BRegion.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" -#include - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBRegion, false) - -////////////////////////////////////////////////////////////////////////// -CBRegion::CBRegion(CBGame *inGame): CBObject(inGame) { - _active = true; - _editorSelectedPoint = -1; - _lastMimicScale = -1; - _lastMimicX = _lastMimicY = INT_MIN; - - CBPlatform::setRectEmpty(&_rect); -} - - -////////////////////////////////////////////////////////////////////////// -CBRegion::~CBRegion() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void CBRegion::cleanup() { - for (int i = 0; i < _points.getSize(); i++) delete _points[i]; - _points.removeAll(); - - CBPlatform::setRectEmpty(&_rect); - _editorSelectedPoint = -1; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegion::createRegion() { - return DID_SUCCEED(getBoundingRect(&_rect)); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegion::pointInRegion(int x, int y) { - if (_points.getSize() < 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 (CBPlatform::ptInRect(&_rect, pt)) return ptInPolygon(x, y); - else return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegion::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CBRegion::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CBRegion::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; - CBParser parser(_gameRef); - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_REGION) { - _gameRef->LOG(0, "'REGION' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - int i; - - for (i = 0; i < _points.getSize(); i++) delete _points[i]; - _points.removeAll(); - - 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 CBPoint(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 CBRegion::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CBPoint(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 < _points.getSize()) { - _points.insertAt(Index, new CBPoint(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 < _points.getSize()) { - _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 < _points.getSize()) { - delete _points[index]; - _points[index] = NULL; - - _points.removeAt(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 < _points.getSize()) { - CScValue *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 CBObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBRegion::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(_name); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Active") == 0) { - _scValue->setBool(_active); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumPoints - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumPoints") == 0) { - _scValue->setInt(_points.getSize()); - return _scValue; - } - - else return CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegion::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBRegion::scToString() { - return "[region]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegion::saveAsText(CBDynBuffer *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", _name); - 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); - - int i; - - for (i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - for (i = 0; i < _points.getSize(); 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 CBRegion::persist(CBPersistMgr *persistMgr) { - - CBObject::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 CBRegion::ptInPolygon(int x, int y) { - if (_points.getSize() < 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 (int i = 1; i <= _points.getSize(); i++) { - p2.x = (double)_points[i % _points.getSize()]->x; - p2.y = (double)_points[i % _points.getSize()]->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 CBRegion::getBoundingRect(Rect32 *rect) { - if (_points.getSize() == 0) CBPlatform::setRectEmpty(rect); - else { - int MinX = INT_MAX, MinY = INT_MAX, MaxX = INT_MIN, MaxY = INT_MIN; - - for (int i = 0; i < _points.getSize(); 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); - } - CBPlatform::setRect(rect, MinX, MinY, MaxX, MaxY); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegion::mimic(CBRegion *region, float scale, int x, int y) { - if (scale == _lastMimicScale && x == _lastMimicX && y == _lastMimicY) return STATUS_OK; - - cleanup(); - - for (int i = 0; i < region->_points.getSize(); 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 CBPoint(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/BRegion.h b/engines/wintermute/base/BRegion.h deleted file mode 100644 index 2a92d9daff..0000000000 --- a/engines/wintermute/base/BRegion.h +++ /dev/null @@ -1,68 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BREGION_H -#define WINTERMUTE_BREGION_H - -#include "engines/wintermute/base/BPoint.h" -#include "engines/wintermute/base/BObject.h" - -namespace WinterMute { - -class CBRegion : public CBObject { -public: - float _lastMimicScale; - int _lastMimicX; - int _lastMimicY; - void cleanup(); - bool mimic(CBRegion *region, float scale = 100.0f, int x = 0, int y = 0); - bool getBoundingRect(Rect32 *rect); - bool ptInPolygon(int x, int y); - DECLARE_PERSISTENT(CBRegion, CBObject) - bool _active; - int _editorSelectedPoint; - CBRegion(CBGame *inGame); - virtual ~CBRegion(); - bool pointInRegion(int x, int y); - bool createRegion(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - Rect32 _rect; - CBArray _points; - virtual bool saveAsText(CBDynBuffer *buffer, int indent, const char *nameOverride = NULL); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BRegistry.cpp b/engines/wintermute/base/BRegistry.cpp deleted file mode 100644 index fef09d7479..0000000000 --- a/engines/wintermute/base/BRegistry.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/tinyxml/tinyxml.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BRegistry.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/utils/utils.h" -#include "common/config-manager.h" -#include "common/file.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBRegistry::CBRegistry(CBGame *inGame): CBBase(inGame) { - _iniName = NULL; - - setIniName("./wme.ini"); - loadValues(true); -} - - -////////////////////////////////////////////////////////////////////////// -CBRegistry::~CBRegistry() { - saveValues(); - delete[] _iniName; - _iniName = NULL; -} - - - -////////////////////////////////////////////////////////////////////////// -AnsiString CBRegistry::readString(const AnsiString &subKey, const AnsiString &key, const AnsiString &init) { - AnsiString ret = ""; - - bool found = false; - ret = getValue(_localValues, subKey, key, found); - if (!found) ret = getValue(_values, subKey, key, found); - if (!found) ret = init; - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegistry::writeString(const AnsiString &subKey, const AnsiString &key, const AnsiString &value) { - _values[subKey][key] = value; - return true; -} - - -////////////////////////////////////////////////////////////////////////// -int CBRegistry::readInt(const AnsiString &subKey, const AnsiString &key, int init) { - if (subKey == "Audio") { - if (key == "MasterVolume") { - if (ConfMan.hasKey("master_volume")) { - return ConfMan.getInt("master_volume"); - } else { - return init; - } - } else if (key == "SFXVolume") { - if (ConfMan.hasKey("sfx_volume")) { - error("This key shouldn't be read by the scripts"); - } else { - return init; - } - } else if (key == "SpeechVolume") { - if (ConfMan.hasKey("speech_volume")) { - error("This key shouldn't be read by the scripts"); - } else { - return init; - } - } else if (key == "MusicVolume") { - if (ConfMan.hasKey("music_volume")) { - error("This key shouldn't be read by the scripts"); - } else { - return init; - } - } - } - AnsiString val = readString(subKey, key, ""); - if (val.empty()) return init; - else return atoi(val.c_str()); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegistry::writeInt(const AnsiString &subKey, const AnsiString &key, int value) { - if (subKey == "Audio") { - if (key == "MasterVolume") { - ConfMan.setInt("master_volume", value); - return true; - } else if (key == "SFXVolume") { - error("This key shouldn't be read by the scripts"); - return true; - } else if (key == "SpeechVolume") { - error("This key shouldn't be read by the scripts"); - return true; - } else if (key == "MusicVolume") { - error("This key shouldn't be read by the scripts"); - return true; - } - } - writeString(subKey, key, StringUtil::toString(value)); - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegistry::readBool(const AnsiString &subKey, const AnsiString &key, bool init) { - return (readInt(subKey, key, (int)init) != 0); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBRegistry::writeBool(const AnsiString &subKey, const AnsiString &key, bool value) { - return writeInt(subKey, key, (int)value); -} - - -////////////////////////////////////////////////////////////////////////// -void CBRegistry::setIniName(const char *name) { - delete[] _iniName; - _iniName = NULL; - - if (strchr(name, '\\') == NULL && strchr(name, '/') == NULL) { - _iniName = new char [strlen(name) + 3]; - sprintf(_iniName, "./%s", name); - } else { - _iniName = new char [strlen(name) + 1]; - strcpy(_iniName, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -char *CBRegistry::getIniName() { - return _iniName; -} - -////////////////////////////////////////////////////////////////////////// -void CBRegistry::loadValues(bool local) { - if (local) loadXml("settings.xml", _localValues); - else loadXml(PathUtil::combine(_gameRef->getDataDir(), "settings.xml"), _values); -} - -////////////////////////////////////////////////////////////////////////// -void CBRegistry::saveValues() { - saveXml(PathUtil::combine(_gameRef->getDataDir(), "settings.xml"), _values); -} - -////////////////////////////////////////////////////////////////////////// -void CBRegistry::setBasePath(const char *basePath) { - _basePath = PathUtil::getFileNameWithoutExtension(basePath); - - loadValues(false); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString CBRegistry::getValue(PathValueMap &values, const AnsiString path, const AnsiString &key, bool &found) { - found = false; - PathValueMap::iterator it = values.find(path); - if (it == values.end()) return ""; - - KeyValuePair pairs = (*it)._value; - KeyValuePair::iterator keyIt = pairs.find(key); - if (keyIt == pairs.end()) return ""; - else { - found = true; - return (*keyIt)._value; - } -} - -////////////////////////////////////////////////////////////////////////// -void CBRegistry::loadXml(const AnsiString fileName, PathValueMap &values) { - TiXmlDocument doc(fileName.c_str()); - if (!doc.LoadFile()) return; - - TiXmlElement *rootElem = doc.RootElement(); - if (!rootElem || Common::String(rootElem->Value()) != "Settings") // TODO: Avoid this strcmp-use. (Hack for now, since we might drop TinyXML all together) - return; - - for (TiXmlElement *pathElem = rootElem->FirstChildElement(); pathElem != NULL; pathElem = pathElem->NextSiblingElement()) { - for (TiXmlElement *keyElem = pathElem->FirstChildElement(); keyElem != NULL; keyElem = keyElem->NextSiblingElement()) { - values[Common::String(pathElem->Value())][Common::String(keyElem->Value())] = keyElem->GetText(); - } - } -} - - -////////////////////////////////////////////////////////////////////////// -void CBRegistry::saveXml(const AnsiString fileName, PathValueMap &values) { - CBUtils::createPath(fileName.c_str()); - - TiXmlDocument doc; - doc.LinkEndChild(new TiXmlDeclaration("1.0", "utf-8", "")); - - TiXmlElement *root = new TiXmlElement("Settings"); - doc.LinkEndChild(root); - - PathValueMap::iterator pathIt; - for (pathIt = _values.begin(); pathIt != _values.end(); ++pathIt) { - TiXmlElement *pathElem = new TiXmlElement((*pathIt)._key.c_str()); - root->LinkEndChild(pathElem); - - - KeyValuePair pairs = (*pathIt)._value; - KeyValuePair::iterator keyIt; - for (keyIt = pairs.begin(); keyIt != pairs.end(); ++keyIt) { - TiXmlElement *keyElem = new TiXmlElement((*keyIt)._key.c_str()); - pathElem->LinkEndChild(keyElem); - - keyElem->LinkEndChild(new TiXmlText((*keyIt)._value.c_str())); - } - } - - - TiXmlPrinter printer; - doc.Accept(&printer); - - Common::DumpFile stream; - stream.open(fileName.c_str()); - - if (!stream.isOpen()) return; - else { - stream.write(printer.CStr(), printer.Size()); - stream.close(); - } -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BRegistry.h b/engines/wintermute/base/BRegistry.h deleted file mode 100644 index 123d1d8a2f..0000000000 --- a/engines/wintermute/base/BRegistry.h +++ /dev/null @@ -1,76 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BREGISTRY_H -#define WINTERMUTE_BREGISTRY_H - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBRegistry : public CBBase { -public: - void setIniName(const char *name); - char *getIniName(); - bool writeBool(const AnsiString &subKey, const AnsiString &key, bool Value); - bool readBool(const AnsiString &subKey, const AnsiString &key, bool init = false); - bool writeInt(const AnsiString &subKey, const AnsiString &key, int value); - int readInt(const AnsiString &subKey, const AnsiString &key, int init = 0); - bool writeString(const AnsiString &subKey, const AnsiString &key, const AnsiString &value); - AnsiString readString(const AnsiString &subKey, const AnsiString &key, const AnsiString &init = ""); - CBRegistry(CBGame *inGame); - virtual ~CBRegistry(); - - void setBasePath(const char *basePath); - AnsiString getBasePath() const { - return _basePath; - } - - void loadValues(bool local); - void saveValues(); - -private: - char *_iniName; - - typedef Common::HashMap KeyValuePair; - typedef Common::HashMap PathValueMap; - - PathValueMap _localValues; - PathValueMap _values; - - AnsiString _basePath; - - void loadXml(const AnsiString fileName, PathValueMap &values); - void saveXml(const AnsiString fileName, PathValueMap &values); - - AnsiString getValue(PathValueMap &values, const AnsiString path, const AnsiString &key, bool &found); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BResources.cpp b/engines/wintermute/base/BResources.cpp deleted file mode 100644 index 839be570c5..0000000000 --- a/engines/wintermute/base/BResources.cpp +++ /dev/null @@ -1,2820 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BResources.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 *CBResources::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; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BResources.h b/engines/wintermute/base/BResources.h deleted file mode 100644 index 6ec0541b5c..0000000000 --- a/engines/wintermute/base/BResources.h +++ /dev/null @@ -1,44 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BRESOURCES_H -#define WINTERMUTE_BRESOURCES_H - -#include "common/stream.h" -#include "common/str.h" - -namespace WinterMute { - -class CBResources { -public: - static Common::SeekableReadStream *getFile(const Common::String &fileName); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BSaveThumbHelper.cpp b/engines/wintermute/base/BSaveThumbHelper.cpp deleted file mode 100644 index 415d4ed1e4..0000000000 --- a/engines/wintermute/base/BSaveThumbHelper.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BSaveThumbHelper.h" -#include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/base/BGame.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBSaveThumbHelper::CBSaveThumbHelper(CBGame *inGame): CBBase(inGame) { - _thumbnail = NULL; -} - -////////////////////////////////////////////////////////////////////////// -CBSaveThumbHelper::~CBSaveThumbHelper(void) { - delete _thumbnail; - _thumbnail = NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSaveThumbHelper::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(); - } - - CBImage *screenshot = _gameRef->_renderer->takeScreenshot(); - if (!screenshot) return STATUS_FAILED; - - // normal thumbnail - if (_gameRef->_thumbnailWidth > 0 && _gameRef->_thumbnailHeight > 0) { - _thumbnail = new CBImage(_gameRef); - _thumbnail->copyFrom(screenshot, _gameRef->_thumbnailWidth, _gameRef->_thumbnailHeight); - } - - - delete screenshot; - screenshot = NULL; - } - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BSaveThumbHelper.h b/engines/wintermute/base/BSaveThumbHelper.h deleted file mode 100644 index 30db32cfb2..0000000000 --- a/engines/wintermute/base/BSaveThumbHelper.h +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ -#ifndef WINTERMUTE_BSAVETHUMBHELPER_H -#define WINTERMUTE_BSAVETHUMBHELPER_H - - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBImage; - -class CBSaveThumbHelper : public CBBase { -public: - CBSaveThumbHelper(CBGame *inGame); - virtual ~CBSaveThumbHelper(void); - bool storeThumbnail(bool doFlip = false); - - CBImage *_thumbnail; - CBImage *_richThumbnail; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BScriptHolder.cpp b/engines/wintermute/base/BScriptHolder.cpp deleted file mode 100644 index 65d37b2e5c..0000000000 --- a/engines/wintermute/base/BScriptHolder.cpp +++ /dev/null @@ -1,473 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ad/AdGame.h" -#include "engines/wintermute/base/BScriptHolder.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBScriptHolder, false) - -////////////////////////////////////////////////////////////////////// -CBScriptHolder::CBScriptHolder(CBGame *inGame): CBScriptable(inGame) { - setName(""); - - _freezable = true; - _filename = NULL; -} - - -////////////////////////////////////////////////////////////////////// -CBScriptHolder::~CBScriptHolder() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::cleanup() { - delete[] _filename; - _filename = NULL; - - int i; - - for (i = 0; i < _scripts.getSize(); i++) { - _scripts[i]->finish(true); - _scripts[i]->_owner = NULL; - } - _scripts.removeAll(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////// -void CBScriptHolder::setFilename(const char *filename) { - if (_filename != NULL) delete [] _filename; - - _filename = new char [strlen(filename) + 1]; - if (_filename != NULL) strcpy(_filename, filename); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::applyEvent(const char *eventName, bool unbreakable) { - int numHandlers = 0; - - bool ret = STATUS_FAILED; - for (int i = 0; i < _scripts.getSize(); i++) { - if (!_scripts[i]->_thread) { - CScScript *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 CBScriptHolder::listen(CBScriptHolder *param1, uint32 param2) { - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); - CScValue *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 (int i = 0; i < _scripts.getSize(); 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 (int i = 0; i < _scripts.getSize(); 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 CBScriptable::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBScriptHolder::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(_name); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Filename (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Filename") == 0) { - _scValue->setString(_filename); - return _scValue; - } - - else return CBScriptable::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::scSetProperty(const char *name, CScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - return STATUS_OK; - } else return CBScriptable::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBScriptHolder::scToString() { - return "[script_holder]"; -} - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::saveAsText(CBDynBuffer *buffer, int indent) { - return CBBase::saveAsText(buffer, indent); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::persist(CBPersistMgr *persistMgr) { - CBScriptable::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_filename)); - persistMgr->transfer(TMEMBER(_freezable)); - persistMgr->transfer(TMEMBER(_name)); - _scripts.persist(persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::addScript(const char *filename) { - for (int i = 0; i < _scripts.getSize(); i++) { - if (scumm_stricmp(_scripts[i]->_filename, filename) == 0) { - if (_scripts[i]->_state != SCRIPT_FINISHED) { - _gameRef->LOG(0, "CBScriptHolder::AddScript - trying to add script '%s' mutiple times (obj: '%s')", filename, _name); - return STATUS_OK; - } - } - } - - CScScript *scr = _gameRef->_scEngine->runScript(filename, this); - if (!scr) { - if (_gameRef->_editorForceScripts) { - // editor hack - scr = new CScScript(_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); - _gameRef->getDebugMgr()->onScriptInit(scr); - - return STATUS_OK; - } - return STATUS_FAILED; - } else { - scr->_freezable = _freezable; - _scripts.add(scr); - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::removeScript(CScScript *script) { - for (int i = 0; i < _scripts.getSize(); i++) { - if (_scripts[i] == script) { - _scripts.removeAt(i); - break; - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::canHandleEvent(const char *EventName) { - for (int i = 0; i < _scripts.getSize(); i++) { - if (!_scripts[i]->_thread && _scripts[i]->canHandleEvent(EventName)) return true; - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::canHandleMethod(const char *MethodName) { - for (int i = 0; i < _scripts.getSize(); 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 CBScriptHolder::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; - CBParser parser(_gameRef); - - 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; - } - - - CScValue *val = new CScValue(_gameRef); - val->setString(propValue); - scSetProperty(propName, val); - - delete val; - delete[] propName; - delete[] propValue; - propName = NULL; - propValue = NULL; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CBScriptHolder::makeFreezable(bool freezable) { - _freezable = freezable; - for (int i = 0; i < _scripts.getSize(); i++) - _scripts[i]->_freezable = freezable; - -} - - -////////////////////////////////////////////////////////////////////////// -CScScript *CBScriptHolder::invokeMethodThread(const char *methodName) { - for (int i = _scripts.getSize() - 1; i >= 0; i--) { - if (_scripts[i]->canHandleMethod(methodName)) { - - CScScript *thread = new CScScript(_gameRef, _scripts[i]->_engine); - if (thread) { - bool ret = thread->createMethodThread(_scripts[i], methodName); - if (DID_SUCCEED(ret)) { - _scripts[i]->_engine->_scripts.add(thread); - _gameRef->getDebugMgr()->onScriptMethodThreadInit(thread, _scripts[i], methodName); - - return thread; - } else { - delete thread; - } - } - } - } - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void CBScriptHolder::scDebuggerDesc(char *buf, int bufSize) { - strcpy(buf, scToString()); - if (_name && strcmp(_name, "") != 0) { - strcat(buf, " Name: "); - strcat(buf, _name); - } - if (_filename) { - strcat(buf, " File: "); - strcat(buf, _filename); - } -} - - -////////////////////////////////////////////////////////////////////////// -// IWmeObject -////////////////////////////////////////////////////////////////////////// -bool CBScriptHolder::sendEvent(const char *eventName) { - return DID_SUCCEED(applyEvent(eventName)); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BScriptHolder.h b/engines/wintermute/base/BScriptHolder.h deleted file mode 100644 index 1e82b8cacf..0000000000 --- a/engines/wintermute/base/BScriptHolder.h +++ /dev/null @@ -1,74 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSCRIPTHOLDER_H -#define WINTERMUTE_BSCRIPTHOLDER_H - -#include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/base/BScriptable.h" - -namespace WinterMute { - -class CBScriptHolder : public CBScriptable { -public: - DECLARE_PERSISTENT(CBScriptHolder, CBScriptable) - - CBScriptHolder(CBGame *inGame); - virtual ~CBScriptHolder(); - virtual CScScript *invokeMethodThread(const char *methodName); - virtual void makeFreezable(bool freezable); - bool canHandleEvent(const char *eventName); - virtual bool canHandleMethod(const char *eventMethod); - bool cleanup(); - bool removeScript(CScScript *script); - bool addScript(const char *filename); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - virtual bool listen(CBScriptHolder *param1, uint32 param2); - bool applyEvent(const char *eventName, bool unbreakable = false); - void setFilename(const char *filename); - bool parseProperty(byte *buffer, bool complete = true); - char *_filename; - bool _freezable; - bool _ready; - - CBArray _scripts; - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - virtual void scDebuggerDesc(char *buf, int bufSize); - // IWmeObject -public: - virtual bool sendEvent(const char *eventName); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BScriptable.cpp b/engines/wintermute/base/BScriptable.cpp deleted file mode 100644 index d1e3556a85..0000000000 --- a/engines/wintermute/base/BScriptable.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BScriptable.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/BPersistMgr.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBScriptable, false) - -////////////////////////////////////////////////////////////////////////// -CBScriptable::CBScriptable(CBGame *inGame, bool noValue, bool persistable): CBNamedObject(inGame) { - _refCount = 0; - - if (noValue) _scValue = NULL; - else _scValue = new CScValue(_gameRef); - - _persistable = persistable; - - _scProp = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CBScriptable::~CBScriptable() { - //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 CBScriptable::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - /* - stack->correctParams(0); - stack->pushNULL(); - script->runtimeError("Call to undefined method '%s'.", name); - - return STATUS_OK; - */ - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBScriptable::scGetProperty(const char *name) { - if (!_scProp) _scProp = new CScValue(_gameRef); - if (_scProp) return _scProp->getProp(name); - else return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptable::scSetProperty(const char *name, CScValue *value) { - if (!_scProp) _scProp = new CScValue(_gameRef); - if (_scProp) return _scProp->setProp(name, value); - else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBScriptable::scToString() { - return "[native object]"; -} - -////////////////////////////////////////////////////////////////////////// -void *CBScriptable::scToMemBuffer() { - return (void *)NULL; -} - - -////////////////////////////////////////////////////////////////////////// -int CBScriptable::scToInt() { - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -double CBScriptable::scToFloat() { - return 0.0f; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptable::scToBool() { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -void CBScriptable::scSetString(const char *val) { -} - - -////////////////////////////////////////////////////////////////////////// -void CBScriptable::scSetInt(int val) { -} - - -////////////////////////////////////////////////////////////////////////// -void CBScriptable::scSetFloat(double val) { -} - - -////////////////////////////////////////////////////////////////////////// -void CBScriptable::scSetBool(bool val) { -} - - -////////////////////////////////////////////////////////////////////////// -bool CBScriptable::persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_gameRef)); - persistMgr->transfer(TMEMBER(_refCount)); - persistMgr->transfer(TMEMBER(_scProp)); - persistMgr->transfer(TMEMBER(_scValue)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CBScriptable::scCompare(CBScriptable *val) { - if (this < val) return -1; - else if (this > val) return 1; - else return 0; -} - -////////////////////////////////////////////////////////////////////////// -void CBScriptable::scDebuggerDesc(char *buf, int bufSize) { - strcpy(buf, scToString()); -} - -////////////////////////////////////////////////////////////////////////// -bool CBScriptable::canHandleMethod(const char *eventMethod) { - return false; -} - - -////////////////////////////////////////////////////////////////////////// -CScScript *CBScriptable::invokeMethodThread(const char *methodName) { - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -// IWmeDebugObject -////////////////////////////////////////////////////////////////////////// -const char *CBScriptable::dbgGetNativeClass() { - return getClassName(); -} - -////////////////////////////////////////////////////////////////////////// -IWmeDebugProp *CBScriptable::dbgGetProperty(const char *name) { - return scGetProperty(name); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BScriptable.h b/engines/wintermute/base/BScriptable.h deleted file mode 100644 index 534bd3bdf1..0000000000 --- a/engines/wintermute/base/BScriptable.h +++ /dev/null @@ -1,90 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSCRIPTABLE_H -#define WINTERMUTE_BSCRIPTABLE_H - - -#include "engines/wintermute/base/BNamedObject.h" -#include "engines/wintermute/wme_debugger.h" -#include "engines/wintermute/persistent.h" - -namespace WinterMute { - -class CScValue; -class CScStack; -class CScScript; - -class CBScriptable : public CBNamedObject, public IWmeDebugObject { -public: - virtual CScScript *invokeMethodThread(const char *methodName); - DECLARE_PERSISTENT(CBScriptable, CBNamedObject) - - CBScriptable(CBGame *inGame, bool noValue = false, bool persistable = true); - virtual ~CBScriptable(); - - // high level scripting interface - virtual bool canHandleMethod(const char *eventMethod); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual CScValue *scGetProperty(const char *name); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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(CBScriptable *val); - virtual void scDebuggerDesc(char *buf, int bufSize); - int _refCount; - CScValue *_scValue; - CScValue *_scProp; - -public: - // IWmeDebugObject - const char *dbgGetNativeClass(); - IWmeDebugProp *dbgGetProperty(const char *name); - -}; - -// Implemented in their respective .cpp-files -CBScriptable *makeSXArray(CBGame *inGame, CScStack *stack); -CBScriptable *makeSXDate(CBGame *inGame, CScStack *stack); -CBScriptable *makeSXFile(CBGame *inGame, CScStack *stack); -CBScriptable *makeSXMath(CBGame *inGame); -CBScriptable *makeSXMemBuffer(CBGame *inGame, CScStack *stack); -CBScriptable *makeSXObject(CBGame *inGame, CScStack *stack); -CBScriptable *makeSXStore(CBGame *inGame); -CBScriptable *makeSXString(CBGame *inGame, CScStack *stack); - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BSound.cpp b/engines/wintermute/base/BSound.cpp deleted file mode 100644 index 2b54b39500..0000000000 --- a/engines/wintermute/base/BSound.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BSound.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/base/BSoundBuffer.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBSound, false) - -////////////////////////////////////////////////////////////////////////// -CBSound::CBSound(CBGame *inGame): CBBase(inGame) { - _sound = NULL; - _soundFilename = NULL; - - _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; -} - - -////////////////////////////////////////////////////////////////////////// -CBSound::~CBSound() { - if (_sound) _gameRef->_soundMgr->removeSound(_sound); - _sound = NULL; - - delete[] _soundFilename; - _soundFilename = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::setSound(const char *filename, Audio::Mixer::SoundType type, bool streamed) { - if (_sound) { - _gameRef->_soundMgr->removeSound(_sound); - _sound = NULL; - } - delete[] _soundFilename; - _soundFilename = NULL; - - _sound = _gameRef->_soundMgr->addSound(filename, type, streamed); - if (_sound) { - _soundFilename = new char[strlen(filename) + 1]; - strcpy(_soundFilename, filename); - - _soundType = type; - _soundStreamed = streamed; - - return STATUS_OK; - } else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::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 CBSound::getLength() { - if (_sound) return _sound->getLength(); - else return 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::play(bool looping) { - if (_sound) { - _soundPaused = false; - return _sound->play(looping, _soundPosition); - } else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::stop() { - if (_sound) { - _soundPaused = false; - return _sound->stop(); - } else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::pause(bool freezePaused) { - if (_sound) { - _soundPaused = true; - if (freezePaused) _sound->_freezePaused = true; - return _sound->pause(); - } else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::resume() { - if (_sound && _soundPaused) { - _soundPaused = false; - return _sound->resume(); - } else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::persist(CBPersistMgr *persistMgr) { - if (persistMgr->_saving && _sound) { - _soundPlaying = _sound->isPlaying(); - _soundLooping = _sound->_looping; - _soundPrivateVolume = _sound->_privateVolume; - if (_soundPlaying) - _soundPosition = _sound->getPosition(); - _soundLoopStart = _sound->_loopStart; - _soundFreezePaused = _sound->_freezePaused; - } - - if (persistMgr->_saving) { - _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 CBSound::isPlaying() { - return _sound && _sound->isPlaying(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::isPaused() { - return _sound && _soundPaused; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::setPositionTime(uint32 time) { - if (!_sound) return STATUS_FAILED; - _soundPosition = time; - bool ret = _sound->setPosition(_soundPosition); - if (_sound->isPlaying()) - _soundPosition = 0; - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CBSound::getPositionTime() { - if (!_sound) return 0; - - if (!_sound->isPlaying()) - return 0; - else return _sound->getPosition(); -} - -////////////////////////////////////////////////////////////////////////// -bool CBSound::setVolumePercent(int percent) { - if (!_sound) - return STATUS_FAILED; - else return _sound->setPrivateVolume(percent * 255 / 100); -} - -////////////////////////////////////////////////////////////////////////// -bool CBSound::setVolume(int volume) { - if (!_sound) - return STATUS_FAILED; - else return _sound->setPrivateVolume(volume); -} - -////////////////////////////////////////////////////////////////////////// -bool CBSound::setPrivateVolume(int volume) { - if (!_sound) - return STATUS_FAILED; - else return _sound->_privateVolume = volume; -} - -////////////////////////////////////////////////////////////////////////// -int CBSound::getVolumePercent() { - if (!_sound) - return 0; - else return _sound->_privateVolume * 100 / 255; -} - -////////////////////////////////////////////////////////////////////////// -int CBSound::getVolume() { - if (!_sound) - return 0; - else return _sound->_privateVolume; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSound::setLoopStart(uint32 pos) { - if (!_sound) - return STATUS_FAILED; - else { - _sound->setLoopStart(pos); - return STATUS_OK; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CBSound::setPan(float pan) { - if (_sound) - return _sound->setPan(pan); - else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSound::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/BSound.h b/engines/wintermute/base/BSound.h deleted file mode 100644 index 9dc825e4ac..0000000000 --- a/engines/wintermute/base/BSound.h +++ /dev/null @@ -1,88 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSOUND_H -#define WINTERMUTE_BSOUND_H - -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/dctypes.h" // Added by ClassView -#include "engines/wintermute/persistent.h" -#include "audio/mixer.h" - -namespace WinterMute { - -class CBSoundBuffer; -class CBSound : public CBBase { -public: - bool setPan(float pan); - int _soundPrivateVolume; - 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 _soundPaused; - bool _soundFreezePaused; - bool isPlaying(); - bool isPaused(); - bool _soundPlaying; - bool _soundLooping; - uint32 _soundLoopStart; - uint32 _soundPosition; - DECLARE_PERSISTENT(CBSound, CBBase) - bool resume(); - bool pause(bool freezePaused = false); - bool stop(); - bool play(bool looping = false); - uint32 getLength(); - bool _soundStreamed; - Audio::Mixer::SoundType _soundType; - char *_soundFilename; - bool setSoundSimple(); - bool setSound(const char *filename, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType, bool streamed = false); - CBSound(CBGame *inGame); - virtual ~CBSound(); - - bool ApplyFX(TSFXType type = SFX_NONE, float param1 = 0, float param2 = 0, float param3 = 0, float param4 = 0); - -private: - TSFXType _sFXType; - float _sFXParam1; - float _sFXParam2; - float _sFXParam3; - float _sFXParam4; - CBSoundBuffer *_sound; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BSoundBuffer.cpp b/engines/wintermute/base/BSoundBuffer.cpp deleted file mode 100644 index 4808cc9007..0000000000 --- a/engines/wintermute/base/BSoundBuffer.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFile.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/base/BSoundBuffer.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/utils/utils.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 - -////////////////////////////////////////////////////////////////////////// -CBSoundBuffer::CBSoundBuffer(CBGame *inGame): CBBase(inGame) { - _stream = NULL; - _handle = NULL; -// _sync = NULL; - - _streamed = false; - _filename = NULL; - _file = NULL; - _privateVolume = 255; - _volume = 255; - - _looping = false; - _loopStart = 0; - - _type = Audio::Mixer::kSFXSoundType; - - _freezePaused = false; -} - - -////////////////////////////////////////////////////////////////////////// -CBSoundBuffer::~CBSoundBuffer() { - stop(); - - if (_handle) { - g_system->getMixer()->stopHandle(*_handle); - delete _handle; - _handle = NULL; - } - delete _stream; - _stream = NULL; - - delete[] _filename; - _filename = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void CBSoundBuffer::setStreaming(bool Streamed, uint32 NumBlocks, uint32 BlockSize) { - _streamed = Streamed; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::loadFromFile(const char *filename, bool forceReload) { - warning("BSoundBuffer::LoadFromFile(%s,%d)", filename, forceReload); -#if 0 - if (_stream) { - BASS_StreamFree(_stream); - _stream = NULL; - } -#endif - - // Load a file, but avoid having the File-manager handle the disposal of it. - _file = _gameRef->_fileManager->openFile(filename, true, false); - if (!_file) { - _gameRef->LOG(0, "Error opening sound file '%s'", filename); - return STATUS_FAILED; - } - Common::String strFilename(filename); - 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 { - warning("BSoundBuffer::LoadFromFile - WAVE not supported yet for %s with type %d", filename, waveType); - } - } - } else { - warning("BSoundBuffer::LoadFromFile - Unknown filetype for %s", filename); - } - if (!_stream) { - return STATUS_FAILED; - } - CBUtils::setString(&_filename, filename); - - return STATUS_OK; -#if 0 - BASS_FILEPROCS fileProc; - fileProc.close = CBSoundBuffer::FileCloseProc; - fileProc.read = CBSoundBuffer::FileReadProc; - fileProc.seek = CBSoundBuffer::FileSeekProc; - fileProc.length = CBSoundBuffer::FileLenProc; - - _stream = BASS_StreamCreateFileUser(STREAMFILE_NOBUFFER, 0, &fileProc, (void *)_file); - if (!_stream) { - _gameRef->LOG(0, "BASS error: %d while loading '%s'", BASS_ErrorGetCode(), filename); - return STATUS_FAILED; - } - - CBUtils::setString(&_filename, filename); - - /* - bool res; - bool NewlyCreated = false; - - if(!_soundBuffer || ForceReload || _streamed){ - if(!_file) _file = _gameRef->_fileManager->openFile(filename); - if(!_file){ - _gameRef->LOG(0, "Error opening sound file '%s'", filename); - return STATUS_FAILED; - } - // switch to streamed for big files - if(!_streamed && (_file->GetSize() > MAX_NONSTREAMED_FILE_SIZE && !_gameRef->_forceNonStreamedSounds)) SetStreaming(true); - } - - // create buffer - if(!_soundBuffer){ - NewlyCreated = true; - - res = InitializeBuffer(_file); - if(DID_FAIL(res)){ - _gameRef->LOG(res, "Error creating sound buffer for file '%s'", filename); - return res; - } - } - - - - // store filename - if(!_filename){ - _filename = new char[strlen(filename)+1]; - strcpy(_filename, filename); - } - - // close file (if not streaming) - if(!_streamed && _file){ - _gameRef->_fileManager->closeFile(_file); - _file = NULL; - } - */ - - return STATUS_OK; -#endif -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::play(bool looping, uint32 startSample) { - if (startSample != 0) { - warning("BSoundBuffer::Play - Should start playback at %d, but currently we don't", startSample); - } - if (_handle) { - g_system->getMixer()->stopHandle(*_handle); - delete _handle; - _handle = NULL; - } - 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 CBSoundBuffer::setLooping(bool looping) { - warning("BSoundBuffer::SetLooping(%d) - won't change a playing sound", looping); - _looping = looping; -#if 0 - - - if (_stream) { - BASS_ChannelFlags(_stream, looping ? BASS_SAMPLE_LOOP : 0, BASS_SAMPLE_LOOP); - } -#endif -} - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::resume() { - if (_stream && _handle) { - g_system->getMixer()->pauseHandle(*_handle, false); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::stop() { - if (_stream && _handle) { - g_system->getMixer()->stopHandle(*_handle); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::pause() { - if (_stream && _handle) { - g_system->getMixer()->pauseHandle(*_handle, true); - } - return STATUS_OK; - -} - -////////////////////////////////////////////////////////////////////////// -uint32 CBSoundBuffer::getLength() { - if (_stream) { - uint32 len = _stream->getLength().msecs(); - return len * 1000; - } - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -void CBSoundBuffer::setType(Audio::Mixer::SoundType type) { - _type = type; -} - -////////////////////////////////////////////////////////////////////////// -void CBSoundBuffer::updateVolume() { - setVolume(_privateVolume); -} - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::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 CBSoundBuffer::setPrivateVolume(int volume) { - _privateVolume = volume; - return setVolume(_privateVolume); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::isPlaying() { - if (_stream && _handle) { - return _freezePaused || g_system->getMixer()->isSoundHandleActive(*_handle); - } else { - return false; - } -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CBSoundBuffer::getPosition() { - if (_stream && _handle) { - uint32 pos = g_system->getMixer()->getSoundElapsedTime(*_handle); - return pos; - } - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::setPosition(uint32 pos) { - warning("CBSoundBuffer::SetPosition - not implemented yet"); -#if 0 - if (_stream) { - QWORD pos = BASS_ChannelSeconds2Bytes(_stream, (float)Pos / 1000.0f); - BASS_ChannelSetPosition(_stream, pos, BASS_POS_BYTE); - } -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::setLoopStart(uint32 pos) { - _loopStart = pos; -#if 0 - if (_stream) { - if (_sync) { - BASS_ChannelRemoveSync(_stream, _sync); - _sync = NULL; - } - if (_loopStart > 0) { - QWORD len = BASS_ChannelGetLength(_stream, BASS_POS_BYTE); - _sync = BASS_ChannelSetSync(_stream, BASS_SYNC_POS | BASS_SYNC_MIXTIME, len, CBSoundBuffer::LoopSyncProc, (void *)this); - } - } -#endif - return STATUS_OK; -} -#if 0 -////////////////////////////////////////////////////////////////////////// -void CBSoundBuffer::LoopSyncProc(HSYNC handle, uint32 channel, uint32 data, void *user) { - CBSoundBuffer *soundBuf = static_cast(user); - QWORD pos = BASS_ChannelSeconds2Bytes(channel, (float)soundBuf->GetLoopStart() / 1000.0f); - - if (!BASS_ChannelSetPosition(channel, pos, BASS_POS_BYTE)) - BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); -} -#endif -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::setPan(float pan) { - if (_handle) { - g_system->getMixer()->setChannelBalance(*_handle, (int8)(pan * 127)); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSoundBuffer::applyFX(TSFXType type, float param1, float param2, float param3, float param4) { - warning("CBSoundBuffer::ApplyFX - not implemented yet"); - switch (type) { - case SFX_ECHO: - break; - - case SFX_REVERB: - break; - - default: - break; - } - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BSoundBuffer.h b/engines/wintermute/base/BSoundBuffer.h deleted file mode 100644 index 9384670fbb..0000000000 --- a/engines/wintermute/base/BSoundBuffer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSOUNDBUFFER_H -#define WINTERMUTE_BSOUNDBUFFER_H - - -#include "engines/wintermute/base/BBase.h" -#include "audio/mixer.h" -#include "common/stream.h" - -namespace Audio { -class SeekableAudioStream; -class SoundHandle; -} - -namespace WinterMute { - -class CBFile; -class CBSoundBuffer : public CBBase { -public: - - CBSoundBuffer(CBGame *inGame); - virtual ~CBSoundBuffer(); - - - 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 char *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; - Common::SeekableReadStream *_file; - char *_filename; - bool _streamed; - - int _privateVolume; -private: - int _volume; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BSoundMgr.cpp b/engines/wintermute/base/BSoundMgr.cpp deleted file mode 100644 index 66baa633e4..0000000000 --- a/engines/wintermute/base/BSoundMgr.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BSoundMgr.h" -#include "engines/wintermute/base/BRegistry.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/BSoundBuffer.h" -#include "engines/wintermute/wintermute.h" -#include "common/config-manager.h" -#include "audio/mixer.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -//IMPLEMENT_PERSISTENT(CBSoundMgr, true); - -////////////////////////////////////////////////////////////////////////// -CBSoundMgr::CBSoundMgr(CBGame *inGame): CBBase(inGame) { - _soundAvailable = false; - _volumeMaster = 255; -} - - -////////////////////////////////////////////////////////////////////////// -CBSoundMgr::~CBSoundMgr() { - saveSettings(); - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundMgr::cleanup() { - for (uint32 i = 0; i < _sounds.size(); i++) - delete _sounds[i]; - _sounds.clear(); -#if 0 - BASS_Free(); -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CBSoundMgr::saveSettings() { - if (_soundAvailable) { - _gameRef->_registry->writeInt("Audio", "MasterVolume", _volumeMaster); - } -} - -////////////////////////////////////////////////////////////////////////// -bool CBSoundMgr::initialize() { - _soundAvailable = false; - - if (!g_system->getMixer()->isReady()) { - return STATUS_FAILED; - } - _volumeMaster = _gameRef->_registry->readInt("Audio", "MasterVolume", 255); - _soundAvailable = true; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundMgr::initLoop() { - if (!_soundAvailable) - return STATUS_OK; -#if 0 - - BASS_Update(500); -#endif - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CBSoundBuffer *CBSoundMgr::addSound(const char *filename, Audio::Mixer::SoundType type, bool streamed) { - if (!_soundAvailable) - return NULL; - - CBSoundBuffer *sound; - - // 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 (_gameRef->_fileManager->hasFile(newFile)) { - filename = newFile.c_str(); - } - } - - sound = new CBSoundBuffer(_gameRef); - if (!sound) return NULL; - - sound->setStreaming(streamed); - sound->setType(type); - - - bool res = sound->loadFromFile(filename); - if (DID_FAIL(res)) { - _gameRef->LOG(res, "Error loading sound '%s'", filename); - 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 CBSoundMgr::addSound(CBSoundBuffer *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 CBSoundMgr::removeSound(CBSoundBuffer *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 CBSoundMgr::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_wintermute->syncSoundSettings(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSoundMgr::setVolumePercent(Audio::Mixer::SoundType type, byte percent) { - return setVolume(type, percent * 255 / 100); -} - - -////////////////////////////////////////////////////////////////////////// -byte CBSoundMgr::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 CBSoundMgr::setMasterVolume(byte value) { - _volumeMaster = value; - for (uint32 i = 0; i < _sounds.size(); i++) { - _sounds[i]->updateVolume(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSoundMgr::setMasterVolumePercent(byte percent) { - setMasterVolume(percent * 255 / 100); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -byte CBSoundMgr::getMasterVolumePercent() { - return getMasterVolume() * 100 / 255; -} - -////////////////////////////////////////////////////////////////////////// -byte CBSoundMgr::getMasterVolume() { - return (byte)_volumeMaster; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSoundMgr::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 CBSoundMgr::resumeAll() { - - for (uint32 i = 0; i < _sounds.size(); i++) { - if (_sounds[i]->_freezePaused) { - _sounds[i]->resume(); - _sounds[i]->_freezePaused = false; - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -float CBSoundMgr::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/BSoundMgr.h b/engines/wintermute/base/BSoundMgr.h deleted file mode 100644 index a021abadaa..0000000000 --- a/engines/wintermute/base/BSoundMgr.h +++ /dev/null @@ -1,69 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSOUNDMGR_H -#define WINTERMUTE_BSOUNDMGR_H - -#include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/base/BBase.h" -#include "audio/mixer.h" -#include "common/array.h" - -namespace WinterMute { -class CBSoundBuffer; -class CBSoundMgr : public CBBase { -public: - float posToPan(int x, int y); - bool resumeAll(); - bool pauseAll(bool includingMusic = true); - bool cleanup(); - //DECLARE_PERSISTENT(CBSoundMgr, CBBase); - 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(CBSoundBuffer *sound); - CBSoundBuffer *addSound(const char *filename, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType, bool streamed = false); - bool addSound(CBSoundBuffer *sound, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType); - bool initLoop(); - bool initialize(); - bool _soundAvailable; - CBSoundMgr(CBGame *inGame); - virtual ~CBSoundMgr(); - Common::Array _sounds; - void saveSettings(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BSprite.cpp b/engines/wintermute/base/BSprite.cpp deleted file mode 100644 index c4dfaa3f8d..0000000000 --- a/engines/wintermute/base/BSprite.cpp +++ /dev/null @@ -1,758 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BSprite.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFrame.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BSubFrame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBSprite, false) - -////////////////////////////////////////////////////////////////////// -CBSprite::CBSprite(CBGame *inGame, CBObject *Owner): CBScriptHolder(inGame) { - _editorAllFrames = false; - _owner = Owner; - setDefaults(); -} - - -////////////////////////////////////////////////////////////////////// -CBSprite::~CBSprite() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void CBSprite::setDefaults() { - _currentFrame = -1; - _looping = false; - _lastFrameTime = 0; - _filename = 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 CBSprite::cleanup() { - CBScriptHolder::cleanup(); - - for (int i = 0; i < _frames.getSize(); i++) - delete _frames[i]; - _frames.removeAll(); - - delete[] _editorBgFile; - _editorBgFile = NULL; - - setDefaults(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSprite::draw(int x, int y, CBObject *registerOwner, float zoomX, float zoomY, uint32 alpha) { - GetCurrentFrame(zoomX, zoomY); - if (_currentFrame < 0 || _currentFrame >= _frames.getSize()) 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 CBSprite::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) { - Common::SeekableReadStream *file = _gameRef->_fileManager->openFile(filename); - if (!file) { - _gameRef->LOG(0, "CBSprite::LoadFile failed for file '%s'", filename); - if (_gameRef->_debugDebugMode) return loadFile("invalid_debug.bmp", lifeTime, cacheType); - else return loadFile("invalid.bmp", lifeTime, cacheType); - } else { - _gameRef->_fileManager->closeFile(file); - file = NULL; - } - - bool ret; - - AnsiString ext = PathUtil::getExtension(filename); - if (StringUtil::startsWith(filename, "savegame:", true) || StringUtil::compareNoCase(ext, "bmp") || StringUtil::compareNoCase(ext, "tga") || StringUtil::compareNoCase(ext, "png") || StringUtil::compareNoCase(ext, "jpg")) { - CBFrame *frame = new CBFrame(_gameRef); - CBSubFrame *subframe = new CBSubFrame(_gameRef); - subframe->setSurface(filename, true, 0, 0, 0, lifeTime, true); - if (subframe->_surface == NULL) { - _gameRef->LOG(0, "Error loading simple sprite '%s'", filename); - ret = STATUS_FAILED; - delete frame; - delete subframe; - } else { - CBPlatform::setRect(&subframe->_rect, 0, 0, subframe->_surface->getWidth(), subframe->_surface->getHeight()); - frame->_subframes.add(subframe); - _frames.add(frame); - _currentFrame = 0; - ret = STATUS_OK; - } - } else { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer) { - if (DID_FAIL(ret = loadBuffer(buffer, true, lifeTime, cacheType))) _gameRef->LOG(0, "Error parsing SPRITE file '%s'", filename); - delete [] buffer; - } - } - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, filename); - - - 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 CBSprite::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; - CBParser parser(_gameRef); - - 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; - CBFrame *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 CBFrame(_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 CBSprite::reset() { - if (_frames.getSize() > 0) _currentFrame = 0; - else _currentFrame = -1; - - killAllSounds(); - - _lastFrameTime = 0; - _finished = false; - _moveX = _moveY = 0; -} - - -////////////////////////////////////////////////////////////////////// -bool CBSprite::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 < _frames.getSize() - 1) { - _currentFrame++; - if (_continuous) _canBreak = (_currentFrame == _frames.getSize() - 1); - } else { - if (_looping) { - _currentFrame = 0; - _canBreak = true; - } else { - _finished = true; - _canBreak = true; - } - } - - _lastFrameTime = timer; - } - - _changed = (lastFrame != _currentFrame || (_looping && _frames.getSize() == 1)); - - if (_lastFrameTime == 0) { - _lastFrameTime = timer; - _changed = true; - if (_continuous) _canBreak = (_currentFrame == _frames.getSize() - 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 CBSprite::display(int X, int Y, CBObject *Register, float ZoomX, float ZoomY, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode) { - if (_currentFrame < 0 || _currentFrame >= _frames.getSize()) 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, Register, ZoomX, ZoomY, _precise, Alpha, _editorAllFrames, Rotate, BlendMode); -} - - -////////////////////////////////////////////////////////////////////////// -CBSurface *CBSprite::getSurface() { - // only used for animated textures for 3D models - if (_currentFrame < 0 || _currentFrame >= _frames.getSize()) return NULL; - CBFrame *Frame = _frames[_currentFrame]; - if (Frame && Frame->_subframes.getSize() > 0) { - CBSubFrame *Subframe = Frame->_subframes[0]; - if (Subframe) return Subframe->_surface; - else return NULL; - } else return NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSprite::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float scaleY) { - if (!rect) return false; - - CBPlatform::setRectEmpty(rect); - for (int i = 0; i < _frames.getSize(); i++) { - Rect32 frame; - Rect32 temp; - CBPlatform::copyRect(&temp, rect); - _frames[i]->getBoundingRect(&frame, x, y, scaleX, scaleY); - CBPlatform::unionRect(rect, &temp, &frame); - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CBSprite::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "SPRITE {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - 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); - } - - CBScriptHolder::saveAsText(buffer, indent + 2); - - int i; - - // scripts - for (i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - - for (i = 0; i < _frames.getSize(); i++) { - _frames[i]->saveAsText(buffer, indent + 2); - } - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSprite::persist(CBPersistMgr *persistMgr) { - CBScriptHolder::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 CBSprite::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // GetFrame - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GetFrame") == 0) { - stack->correctParams(1); - int Index = stack->pop()->getInt(-1); - if (Index < 0 || Index >= _frames.getSize()) { - 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); - CScValue *Val = stack->pop(); - if (Val->isInt()) { - int Index = Val->getInt(-1); - if (Index < 0 || Index >= _frames.getSize()) { - script->runtimeError("Sprite.DeleteFrame: Frame index %d is out of range.", Index); - } - } else { - CBFrame *Frame = (CBFrame *)Val->getNative(); - for (int i = 0; i < _frames.getSize(); i++) { - if (_frames[i] == Frame) { - if (i == _currentFrame) _lastFrameTime = 0; - delete _frames[i]; - _frames.removeAt(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); - CScValue *val = stack->pop(); - const char *filename = NULL; - if (!val->isNULL()) filename = val->getString(); - - CBFrame *frame = new CBFrame(_gameRef); - if (filename != NULL) { - CBSubFrame *sub = new CBSubFrame(_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; - - CScValue *val = stack->pop(); - const char *filename = NULL; - if (!val->isNULL()) - filename = val->getString(); - - CBFrame *frame = new CBFrame(_gameRef); - if (filename != NULL) { - CBSubFrame *sub = new CBSubFrame(_gameRef); - if (DID_SUCCEED(sub->setSurface(filename))) frame->_subframes.add(sub); - else delete sub; - } - - if (index >= _frames.getSize()) - _frames.add(frame); - else _frames.insertAt(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 CBScriptHolder::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBSprite::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.getSize()); - 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 CBScriptHolder::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSprite::scSetProperty(const char *name, CScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // CurrentFrame - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "CurrentFrame") == 0) { - _currentFrame = value->getInt(0); - if (_currentFrame >= _frames.getSize() || _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 CBScriptHolder::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBSprite::scToString() { - return "[sprite]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSprite::killAllSounds() { - for (int i = 0; i < _frames.getSize(); i++) { - if (_frames[i]->_sound) - _frames[i]->_sound->stop(); - } - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BSprite.h b/engines/wintermute/base/BSprite.h deleted file mode 100644 index 3c67e5f3fe..0000000000 --- a/engines/wintermute/base/BSprite.h +++ /dev/null @@ -1,90 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSPRITE_H -#define WINTERMUTE_BSPRITE_H - - -#include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/base/BScriptHolder.h" - -namespace WinterMute { -class CBFrame; -class CBSurface; -class CBObject; -class CBSprite: public CBScriptHolder { -public: - bool killAllSounds(); - CBSurface *getSurface(); - char *_editorBgFile; - int _editorBgOffsetX; - int _editorBgOffsetY; - int _editorBgAlpha; - bool _streamed; - bool _streamedKeepLoaded; - void cleanup(); - void setDefaults(); - bool _precise; - DECLARE_PERSISTENT(CBSprite, CBScriptHolder) - - 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, CBObject *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(); - CBObject *_owner; - bool _changed; - bool _paused; - bool _finished; - bool loadBuffer(byte *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); - bool loadFile(const char *filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); - uint32 _lastFrameTime; - bool draw(int x, int y, CBObject *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); - CBSprite(CBGame *inGame, CBObject *owner = NULL); - virtual ~CBSprite(); - CBArray _frames; - bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BStringTable.cpp b/engines/wintermute/base/BStringTable.cpp deleted file mode 100644 index 470ae8549c..0000000000 --- a/engines/wintermute/base/BStringTable.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFileManager.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "common/str.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBStringTable::CBStringTable(CBGame *inGame): CBBase(inGame) { - -} - - -////////////////////////////////////////////////////////////////////////// -CBStringTable::~CBStringTable() { - // delete strings - _strings.clear(); - -} - - -////////////////////////////////////////////////////////////////////////// -bool CBStringTable::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 = _strings.find(finalKey); - if (_stringsIter != _strings.end() && reportDuplicities) _gameRef->LOG(0, " Warning: Duplicate definition of string '%s'.", finalKey.c_str()); - - _strings[finalKey] = val; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -char *CBStringTable::getKey(const char *str) { - if (str == NULL || str[0] != '/') return NULL; - - const char *value = strchr(str + 1, '/'); - if (value == NULL) return NULL; - - char *key = new char[value - str]; - strncpy(key, str + 1, value - str - 1); - key[value - str - 1] = '\0'; - CBPlatform::strlwr(key); - - char *new_str; - - _stringsIter = _strings.find(key); - if (_stringsIter != _strings.end()) { - new_str = new char[_stringsIter->_value.size() + 1]; - strcpy(new_str, _stringsIter->_value.c_str()); - if (strlen(new_str) > 0 && new_str[0] == '/' && strchr(new_str + 1, '/')) { - delete [] key; - char *Ret = getKey(new_str); - delete [] new_str; - return Ret; - } else { - delete [] new_str; - return key; - } - } else { - return key; - } -} - -////////////////////////////////////////////////////////////////////////// -void CBStringTable::expand(char **str, bool forceExpand) { - if (_gameRef->_doNotExpandStrings && !forceExpand) return; - - if (str == NULL || *str == NULL || *str[0] != '/') return; - - char *value = strchr(*str + 1, '/'); - if (value == NULL) return; - - char *key = new char[value - *str]; - strncpy(key, *str + 1, value - *str - 1); - key[value - *str - 1] = '\0'; - CBPlatform::strlwr(key); - - value++; - - char *new_str; - - _stringsIter = _strings.find(key); - if (_stringsIter != _strings.end()) { - new_str = new char[_stringsIter->_value.size() + 1]; - strcpy(new_str, _stringsIter->_value.c_str()); - } else { - new_str = new char[strlen(value) + 1]; - strcpy(new_str, value); - } - - delete [] key; - delete [] *str; - *str = new_str; - - if (strlen(*str) > 0 && *str[0] == '/') expand(str, forceExpand); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBStringTable::expandStatic(const char *string, bool forceExpand) { - if (_gameRef->_doNotExpandStrings && !forceExpand) return string; - - 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]; - strncpy(key, string + 1, value - string - 1); - key[value - string - 1] = '\0'; - CBPlatform::strlwr(key); - - value++; - - const char *new_str; - - _stringsIter = _strings.find(key); - if (_stringsIter != _strings.end()) { - new_str = _stringsIter->_value.c_str(); - } else { - new_str = value; - } - - delete [] key; - - if (strlen(new_str) > 0 && new_str[0] == '/') return expandStatic(new_str, forceExpand); - else return new_str; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBStringTable::loadFile(const char *filename, bool clearOld) { - _gameRef->LOG(0, "Loading string table..."); - - if (clearOld) _strings.clear(); - - uint32 size; - byte *buffer = _gameRef->_fileManager->readWholeFile(filename, &size); - if (buffer == NULL) { - _gameRef->LOG(0, "CBStringTable::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]; - strncpy(line, (char *)&buffer[pos], realLength); - line[realLength] = '\0'; - 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/BStringTable.h b/engines/wintermute/base/BStringTable.h deleted file mode 100644 index 92d3604b4d..0000000000 --- a/engines/wintermute/base/BStringTable.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSTRINGTABLE_H -#define WINTERMUTE_BSTRINGTABLE_H - - -#include "common/hashmap.h" -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBStringTable : public CBBase { -public: - const char *expandStatic(const char *string, bool forceExpand = false); - bool loadFile(const char *filename, bool deleteAll = true); - void expand(char **str, bool forceExpand = false); - bool addString(const char *key, const char *val, bool reportDuplicities = true); - CBStringTable(CBGame *inGame); - virtual ~CBStringTable(); - Common::HashMap _strings; - char *getKey(const char *str); -private: - Common::HashMap::iterator _stringsIter; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BSubFrame.cpp b/engines/wintermute/base/BSubFrame.cpp deleted file mode 100644 index 858f2125c6..0000000000 --- a/engines/wintermute/base/BSubFrame.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BParser.h" -#include "engines/wintermute/base/BSubFrame.h" -#include "engines/wintermute/base/BActiveRect.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/BSurfaceStorage.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBSubFrame, false) - -////////////////////////////////////////////////////////////////////////// -CBSubFrame::CBSubFrame(CBGame *inGame): CBScriptable(inGame, true) { - _surface = NULL; - _hotspotX = _hotspotY = 0; - _alpha = 0xFFFFFFFF; - _transparent = 0xFFFF00FF; - - CBPlatform::setRectEmpty(&_rect); - - _editorSelected = false; - - _surfaceFilename = NULL; - _cKDefault = true; - _cKRed = _cKBlue = _cKGreen = 0; - _lifeTime = -1; - _keepLoaded = false; - - _2DOnly = _3DOnly = false; - _decoration = false; - - _mirrorX = _mirrorY = false; -} - - -////////////////////////////////////////////////////////////////////////// -CBSubFrame::~CBSubFrame() { - 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 CBSubFrame::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; - CBParser parser(_gameRef); - Rect32 rect; - int r = 255, g = 255, b = 255; - int ar = 255, ag = 255, ab = 255, alpha = 255; - bool custoTrans = false; - CBPlatform::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 (CBPlatform::isRectEmpty(&rect)) setDefaultRect(); - else _rect = rect; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////// -bool CBSubFrame::draw(int x, int y, CBObject *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->_rectList.add(new CBActiveRect(_gameRef, registerOwner, this, x - _hotspotX + _rect.left, y - _hotspotY + _rect.top, _rect.right - _rect.left, _rect.bottom - _rect.top, zoomX, zoomY, precise)); - } else { - _gameRef->_renderer->_rectList.add(new CBActiveRect(_gameRef, registerOwner, this, (int)(x - (_hotspotX + _rect.left) * (zoomX / 100)), (int)(y - (_hotspotY + _rect.top) * (zoomY / 100)), (int)((_rect.right - _rect.left) * (zoomX / 100)), (int)((_rect.bottom - _rect.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, _rect, zoomX, zoomY, alpha, rotate, blendMode, _mirrorX, _mirrorY); - } else { - if (zoomX == 100 && zoomY == 100) res = _surface->displayTrans(x - _hotspotX, y - _hotspotY, _rect, alpha, blendMode, _mirrorX, _mirrorY); - else res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), _rect, zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY); - } - - return res; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSubFrame::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; - - CBPlatform::setRect(rect, - (int)(x - _hotspotX * ratioX), - (int)(y - _hotspotY * ratioY), - (int)(x - _hotspotX * ratioX + (_rect.right - _rect.left) * ratioX), - (int)(y - _hotspotY * ratioY + (_rect.bottom - _rect.top) * ratioY)); - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSubFrame::saveAsText(CBDynBuffer *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; - CBPlatform::setRectEmpty(&rect); - if (_surface) CBPlatform::setRect(&rect, 0, 0, _surface->getWidth(), _surface->getHeight()); - if (!CBPlatform::equalRect(&rect, &_rect)) - buffer->putTextIndent(indent + 2, "RECT { %d,%d,%d,%d }\n", _rect.left, _rect.top, _rect.right, _rect.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"); - - CBBase::saveAsText(buffer, indent + 2); - - - if (complete) - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CBSubFrame::setDefaultRect() { - if (_surface) { - CBPlatform::setRect(&_rect, 0, 0, _surface->getWidth(), _surface->getHeight()); - } else CBPlatform::setRectEmpty(&_rect); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSubFrame::persist(CBPersistMgr *persistMgr) { - - CBScriptable::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(_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 CBSubFrame::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); - CScValue *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 CBScriptable::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CBSubFrame::scGetProperty(const char *name) { - if (!_scValue) _scValue = new CScValue(_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 CBScriptable::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSubFrame::scSetProperty(const char *name, CScValue *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 CBScriptable::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CBSubFrame::scToString() { - return "[subframe]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSubFrame::setSurface(const char *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[strlen(filename) + 1]; - strcpy(_surfaceFilename, filename); - - _cKDefault = defaultCK; - _cKRed = ckRed; - _cKGreen = ckGreen; - _cKBlue = ckBlue; - _lifeTime = lifeTime; - _keepLoaded = keepLoaded; - - return STATUS_OK; - } else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSubFrame::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/BSubFrame.h b/engines/wintermute/base/BSubFrame.h deleted file mode 100644 index 57ffcae675..0000000000 --- a/engines/wintermute/base/BSubFrame.h +++ /dev/null @@ -1,86 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSUBFRAME_H -#define WINTERMUTE_BSUBFRAME_H - - -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/base/BScriptable.h" - -namespace WinterMute { -class CBObject; -class CBSurface; -class CBSubFrame : public CBScriptable { -public: - bool _mirrorX; - bool _mirrorY; - bool _decoration; - bool setSurface(const char *filename, bool defaultCK = true, byte ckRed = 0, byte ckGreen = 0, byte ckBlue = 0, int lifeTime = -1, bool keepLoaded = false); - bool setSurfaceSimple(); - DECLARE_PERSISTENT(CBSubFrame, CBScriptable) - void setDefaultRect(); - uint32 _transparent; - bool saveAsText(CBDynBuffer *buffer, int indent) { return saveAsText(buffer, indent, true); } - bool saveAsText(CBDynBuffer *buffer, int indent, bool complete); - bool _editorSelected; - CBSubFrame(CBGame *inGame); - virtual ~CBSubFrame(); - bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded); - bool draw(int x, int y, CBObject *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; - Rect32 _rect; - - bool _cKDefault; - byte _cKRed; - byte _cKGreen; - byte _cKBlue; - int _lifeTime; - bool _keepLoaded; - char *_surfaceFilename; - - bool _2DOnly; - bool _3DOnly; - - CBSurface *_surface; - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BSurfaceStorage.cpp b/engines/wintermute/base/BSurfaceStorage.cpp deleted file mode 100644 index 406535cf39..0000000000 --- a/engines/wintermute/base/BSurfaceStorage.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BSurfaceStorage.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace WinterMute { - -//IMPLEMENT_PERSISTENT(CBSurfaceStorage, true); - -////////////////////////////////////////////////////////////////////// -CBSurfaceStorage::CBSurfaceStorage(CBGame *inGame): CBBase(inGame) { - _lastCleanupTime = 0; -} - - -////////////////////////////////////////////////////////////////////// -CBSurfaceStorage::~CBSurfaceStorage() { - cleanup(true); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSurfaceStorage::cleanup(bool warn) { - for (uint32 i = 0; i < _surfaces.size(); i++) { - if (warn) _gameRef->LOG(0, "CBSurfaceStorage warning: purging surface '%s', usage:%d", _surfaces[i]->getFileName(), _surfaces[i]->_referenceCount); - delete _surfaces[i]; - } - _surfaces.clear(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSurfaceStorage::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 && _gameRef->_liveTimer - _surfaces[i]->_lastUsedTime >= _surfaces[i]->_lifeTime) { - //_gameRef->QuickMessageForm("Invalidating: %s", _surfaces[i]->_filename); - _surfaces[i]->invalidate(); - } - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////// -bool CBSurfaceStorage::removeSurface(CBSurface *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; -} - - -////////////////////////////////////////////////////////////////////// -CBSurface *CBSurfaceStorage::addSurface(const char *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) == 0) { - _surfaces[i]->_referenceCount++; - return _surfaces[i]; - } - } - - if (!_gameRef->_fileManager->hasFile(filename)) { - if (filename) _gameRef->LOG(0, "Missing image: '%s'", filename); - 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); - } - - CBSurface *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 CBSurfaceStorage::restoreAll() { - bool ret; - for (uint32 i = 0; i < _surfaces.size(); i++) { - ret = _surfaces[i]->restore(); - if (ret != STATUS_OK) { - _gameRef->LOG(0, "CBSurfaceStorage::RestoreAll failed"); - return ret; - } - } - return STATUS_OK; -} - - -/* -////////////////////////////////////////////////////////////////////////// -bool CBSurfaceStorage::persist(CBPersistMgr *persistMgr) -{ - - if(!persistMgr->_saving) cleanup(false); - - persistMgr->transfer(TMEMBER(_gameRef)); - - //_surfaces.persist(persistMgr); - - return STATUS_OK; -} -*/ - - -////////////////////////////////////////////////////////////////////////// -bool CBSurfaceStorage::sortSurfaces() { - qsort(&_surfaces[0], _surfaces.size(), sizeof(CBSurface *), surfaceSortCB); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CBSurfaceStorage::surfaceSortCB(const void *arg1, const void *arg2) { - CBSurface *s1 = *((CBSurface **)arg1); - CBSurface *s2 = *((CBSurface **)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/BSurfaceStorage.h b/engines/wintermute/base/BSurfaceStorage.h deleted file mode 100644 index c054c2a55b..0000000000 --- a/engines/wintermute/base/BSurfaceStorage.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSURFACESTORAGE_H -#define WINTERMUTE_BSURFACESTORAGE_H - -#include "engines/wintermute/base/BBase.h" -#include "common/array.h" - -namespace WinterMute { -class CBSurface; -class CBSurfaceStorage : public CBBase { -public: - uint32 _lastCleanupTime; - bool initLoop(); - bool sortSurfaces(); - static int surfaceSortCB(const void *arg1, const void *arg2); - bool cleanup(bool Warn = false); - //DECLARE_PERSISTENT(CBSurfaceStorage, CBBase); - - bool restoreAll(); - CBSurface *addSurface(const char *filename, bool defaultCK = true, byte ckRed = 0, byte ckGreen = 0, byte ckBlue = 0, int lifeTime = -1, bool keepLoaded = false); - bool removeSurface(CBSurface *surface); - CBSurfaceStorage(CBGame *inGame); - virtual ~CBSurfaceStorage(); - - Common::Array _surfaces; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BTransitionMgr.cpp b/engines/wintermute/base/BTransitionMgr.cpp deleted file mode 100644 index 1cea7285bf..0000000000 --- a/engines/wintermute/base/BTransitionMgr.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BTransitionMgr.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBTransitionMgr::CBTransitionMgr(CBGame *inGame): CBBase(inGame) { - _state = TRANS_MGR_READY; - _type = TRANSITION_NONE; - _origInteractive = false; - _preserveInteractive = false; - _lastTime = 0; - _started = false; -} - - - -////////////////////////////////////////////////////////////////////////// -CBTransitionMgr::~CBTransitionMgr() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CBTransitionMgr::isReady() { - return (_state == TRANS_MGR_READY); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBTransitionMgr::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 CBTransitionMgr::update() { - if (isReady()) return STATUS_OK; - - if (!_started) { - _started = true; - _lastTime = CBPlatform::getTime(); - } - - switch (_type) { - case TRANSITION_NONE: - _state = TRANS_MGR_READY; - break; - - case TRANSITION_FADE_OUT: { - uint32 time = CBPlatform::getTime() - _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 = CBPlatform::getTime() - _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("CBTransitionMgr::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/BTransitionMgr.h b/engines/wintermute/base/BTransitionMgr.h deleted file mode 100644 index faedb6fe3e..0000000000 --- a/engines/wintermute/base/BTransitionMgr.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BTRANSITIONMGR_H -#define WINTERMUTE_BTRANSITIONMGR_H - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBTransitionMgr : public CBBase { -public: - bool _started; - uint32 _lastTime; - bool _origInteractive; - bool _preserveInteractive; - bool update(); - bool start(TTransitionType type, bool nonInteractive = false); - bool isReady(); - TTransMgrState _state; - CBTransitionMgr(CBGame *inGame); - virtual ~CBTransitionMgr(); - TTransitionType _type; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/BViewport.cpp b/engines/wintermute/base/BViewport.cpp deleted file mode 100644 index 2b237a0d38..0000000000 --- a/engines/wintermute/base/BViewport.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/BViewport.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CBViewport, false) - -////////////////////////////////////////////////////////////////////////// -CBViewport::CBViewport(CBGame *inGame): CBBase(inGame) { - CBPlatform::setRectEmpty(&_rect); - _mainObject = NULL; - _offsetX = _offsetY = 0; -} - - -////////////////////////////////////////////////////////////////////////// -CBViewport::~CBViewport() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CBViewport::persist(CBPersistMgr *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 CBViewport::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); - } - - CBPlatform::setRect(&_rect, left, top, right, bottom); - _offsetX = left; - _offsetY = top; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -Rect32 *CBViewport::getRect() { - return &_rect; -} - - -////////////////////////////////////////////////////////////////////////// -int CBViewport::getWidth() { - return _rect.right - _rect.left; -} - - -////////////////////////////////////////////////////////////////////////// -int CBViewport::getHeight() { - return _rect.bottom - _rect.top; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/BViewport.h b/engines/wintermute/base/BViewport.h deleted file mode 100644 index 1150b8ebe7..0000000000 --- a/engines/wintermute/base/BViewport.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BVIEWPORT_H -#define WINTERMUTE_BVIEWPORT_H - - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { -class CBObject; -class CBViewport : public CBBase { -public: - int getHeight(); - int getWidth(); - Rect32 *getRect(); - bool setRect(int left, int top, int right, int bottom, bool noCheck = false); - DECLARE_PERSISTENT(CBViewport, CBBase) - int _offsetY; - int _offsetX; - CBObject *_mainObject; - CBViewport(CBGame *inGame = NULL); - virtual ~CBViewport(); -private: - Rect32 _rect; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/base.cpp b/engines/wintermute/base/base.cpp new file mode 100644 index 0000000000..5fabe94312 --- /dev/null +++ b/engines/wintermute/base/base.cpp @@ -0,0 +1,178 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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.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 { + +////////////////////////////////////////////////////////////////////// +CBBase::CBBase(CBGame *gameOwner) { + _gameRef = gameOwner; + _persistable = true; +} + + +////////////////////////////////////////////////////////////////////////// +CBBase::CBBase() { + _gameRef = NULL; + _persistable = true; +} + + +////////////////////////////////////////////////////////////////////// +CBBase::~CBBase() { + _editorProps.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBBase::getEditorProp(const char *propName, const char *initVal) { + _editorPropsIter = _editorProps.find(propName); + if (_editorPropsIter != _editorProps.end()) + return _editorPropsIter->_value.c_str(); + //return _editorPropsIter->second.c_str(); // <- TODO Clean + else return initVal; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBBase::setEditorProp(const char *propName, const char *propValue) { + if (propName == NULL) return STATUS_FAILED; + + if (propValue == NULL) { + _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 CBBase::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; + CBParser parser(_gameRef); + + 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 CBBase::saveAsText(CBDynBuffer *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 + 2, "NAME=\"%s\"\n", (char *)_editorPropsIter->first.c_str()); // <- TODO, remove + //buffer->putTextIndent(indent + 2, "VALUE=\"%s\"\n", _editorPropsIter->second.c_str()); // <- TODO, remove + buffer->putTextIndent(indent, "}\n\n"); + + _editorPropsIter++; + } + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base.h b/engines/wintermute/base/base.h new file mode 100644 index 0000000000..e8c87f1f9e --- /dev/null +++ b/engines/wintermute/base/base.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BBASE_H +#define WINTERMUTE_BBASE_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 CBGame; +class CBDynBuffer; + +class CBBase { +public: + bool _persistable; + bool setEditorProp(const char *propName, const char *propValue); + const char *getEditorProp(const char *propName, const char *initVal = NULL); + CBBase(TDynamicConstructor, TDynamicConstructor) {}; + bool parseEditorProperty(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent = 0); + CBBase(); + CBGame *_gameRef; + CBBase(CBGame *GameOwner); + virtual ~CBBase(); + + Common::HashMap _editorProps; + Common::HashMap::iterator _editorPropsIter; + /* std::map _editorProps; + std::map::iterator _editorPropsIter;*/ +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_active_rect.cpp b/engines/wintermute/base/base_active_rect.cpp new file mode 100644 index 0000000000..5895b1acd5 --- /dev/null +++ b/engines/wintermute/base/base_active_rect.cpp @@ -0,0 +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 + */ + +#include "engines/wintermute/dcgf.h" +#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 { + +////////////////////////////////////////////////////////////////////// +CBActiveRect::CBActiveRect(CBGame *inGame): CBBase(inGame) { + CBPlatform::setRectEmpty(&_rect); + _owner = NULL; + _frame = NULL; + _region = NULL; + _zoomX = 100; + _zoomY = 100; + _offsetX = _offsetY = 0; + clipRect(); +} + + +////////////////////////////////////////////////////////////////////// +CBActiveRect::CBActiveRect(CBGame *inGame, CBObject *owner, CBSubFrame *frame, int x, int y, int width, int height, float zoomX, float zoomY, bool precise): CBBase(inGame) { + _owner = owner; + _frame = frame; + CBPlatform::setRect(&_rect, x, y, x + width, y + height); + _zoomX = zoomX; + _zoomY = zoomY; + _precise = precise; + _region = NULL; + _offsetX = _offsetY = 0; + clipRect(); +} + +////////////////////////////////////////////////////////////////////// +CBActiveRect::CBActiveRect(CBGame *inGame, CBObject *owner, CBRegion *region, int offsetX, int offsetY): CBBase(inGame) { + _owner = owner; + _region = region; + CBPlatform::copyRect(&_rect, ®ion->_rect); + CBPlatform::offsetRect(&_rect, -offsetX, -offsetY); + _zoomX = 100; + _zoomY = 100; + _precise = true; + _frame = NULL; + clipRect(); + _offsetX = offsetX; + _offsetY = offsetY; +} + + +////////////////////////////////////////////////////////////////////// +CBActiveRect::~CBActiveRect() { + _owner = NULL; + _frame = NULL; + _region = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBActiveRect::clipRect() { + Rect32 rc; + bool customViewport; + _gameRef->getCurrentViewportRect(&rc, &customViewport); + CBRenderer *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; + + CBPlatform::intersectRect(&_rect, &_rect, &rc); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_active_rect.h b/engines/wintermute/base/base_active_rect.h new file mode 100644 index 0000000000..7c9e8d4a39 --- /dev/null +++ b/engines/wintermute/base/base_active_rect.h @@ -0,0 +1,60 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BACTIVERECT_H +#define WINTERMUTE_BACTIVERECT_H + +#include "engines/wintermute/math/rect32.h" +#include "engines/wintermute/base/base.h" + +namespace WinterMute { +class CBRegion; +class CBSubFrame; +class CBObject; +class CBActiveRect: CBBase { +public: + void clipRect(); + bool _precise; + float _zoomX; + float _zoomY; + CBSubFrame *_frame; + CBObject *_owner; + CBRegion *_region; + int _offsetX; + int _offsetY; + Rect32 _rect; + CBActiveRect(CBGame *inGameOwner = NULL); + CBActiveRect(CBGame *inGameOwner, CBObject *owner, CBSubFrame *frame, int x, int y, int width, int height, float zoomX = 100, float zoomY = 100, bool precise = true); + CBActiveRect(CBGame *inGame, CBObject *owner, CBRegion *region, int offsetX, int offsetY); + virtual ~CBActiveRect(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_debugger.cpp b/engines/wintermute/base/base_debugger.cpp new file mode 100644 index 0000000000..f56f08dab2 --- /dev/null +++ b/engines/wintermute/base/base_debugger.cpp @@ -0,0 +1,203 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/base_Debugger.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBDebugger::CBDebugger(CBGame *inGame) : CBBase(inGame) { + _enabled = false; +} + +////////////////////////////////////////////////////////////////////////// +CBDebugger::~CBDebugger(void) { +} + + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::initialize() { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::shutdown() { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onGameInit() { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onGameShutdown() { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onGameTick() { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onLog(unsigned int errorCode, const char *text) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptInit(CScScript *script) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptEventThreadInit(CScScript *script, CScScript *parentScript, const char *name) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptMethodThreadInit(CScScript *script, CScScript *parentScript, const char *name) { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptShutdown(CScScript *script) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptChangeLine(CScScript *script, int Line) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptChangeScope(CScScript *script, CScValue *scope) { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptShutdownScope(CScScript *script, CScValue *scope) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onVariableInit(EWmeDebuggerVariableType type, CScScript *script, CScValue *scope, CScValue *var, const char *variableName) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onVariableChangeValue(CScValue *var, CScValue *value) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::onScriptHitBreakpoint(CScScript *script) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +// IWmeDebugServer interface implementation +bool CBDebugger::attachClient(IWmeDebugClient *client) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::detachClient(IWmeDebugClient *client) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::queryData(IWmeDebugClient *client) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +int CBDebugger::getPropInt(const char *propName) { + return 0; +} + +////////////////////////////////////////////////////////////////////////// +double CBDebugger::getPropFloat(const char *propName) { + return 0.0; +} + +////////////////////////////////////////////////////////////////////////// +const char *CBDebugger::getPropString(const char *propName) { + return ""; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::getPropBool(const char *propName) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::setProp(const char *propName, int propValue) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::setProp(const char *propName, double propValue) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::setProp(const char *propName, const char *propValue) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::setProp(const char *propName, bool propValue) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::resolveFilename(const char *relativeFilename, char *absFilenameBuf, int absBufSize) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::addBreakpoint(const char *scriptFilename, int line) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::removeBreakpoint(const char *scriptFilename, int line) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBDebugger::continueExecution() { + return false; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_debugger.h b/engines/wintermute/base/base_debugger.h new file mode 100644 index 0000000000..35ea56eafe --- /dev/null +++ b/engines/wintermute/base/base_debugger.h @@ -0,0 +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 + */ + +#ifndef WINTERMUTE_BDEBUGGER_H +#define WINTERMUTE_BDEBUGGER_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/wme_debugger.h" + +// TODO: The entire debugger should possibly be removed + +namespace WinterMute { +class CScScript; +class CScValue; +class CBDebugger : public CBBase, public IWmeDebugServer { +public: + CBDebugger(CBGame *inGame); + virtual ~CBDebugger(void); + + // initialization + bool _enabled; + bool initialize(); + bool shutdown(); + + // internal interface + bool onGameInit(); + bool onGameShutdown(); + bool onGameTick(); + bool onLog(unsigned int errorCode, const char *text); + bool onScriptInit(CScScript *script); + bool onScriptEventThreadInit(CScScript *script, CScScript *parentScript, const char *name); + bool onScriptMethodThreadInit(CScScript *script, CScScript *parentScript, const char *name); + + bool onScriptShutdown(CScScript *script); + bool onScriptChangeLine(CScScript *script, int line); + bool onScriptChangeScope(CScScript *script, CScValue *scope); + bool onScriptShutdownScope(CScScript *script, CScValue *scope); + bool onVariableInit(EWmeDebuggerVariableType type, CScScript *script, CScValue *scope, CScValue *var, const char *variableName); + bool onVariableChangeValue(CScValue *var, CScValue *value); + + bool onScriptHitBreakpoint(CScScript *script); + + // IWmeDebugServer interface + virtual bool attachClient(IWmeDebugClient *client); + virtual bool detachClient(IWmeDebugClient *client); + virtual bool queryData(IWmeDebugClient *client); + + virtual int getPropInt(const char *propName); + virtual double getPropFloat(const char *propName); + virtual const char *getPropString(const char *propName); + virtual bool getPropBool(const char *propName); + + virtual bool setProp(const char *propName, int propValue); + virtual bool setProp(const char *propName, double propValue); + virtual bool setProp(const char *propName, const char *propValue); + virtual bool setProp(const char *propName, bool propValue); + + virtual bool resolveFilename(const char *relativeFilename, char *absFilenameBuf, int absBufSize); + + virtual bool addBreakpoint(const char *scriptFilename, int line); + virtual bool removeBreakpoint(const char *scriptFilename, int line); + + virtual bool continueExecution(); +private: +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_dynamic_buffer.cpp b/engines/wintermute/base/base_dynamic_buffer.cpp new file mode 100644 index 0000000000..7453838219 --- /dev/null +++ b/engines/wintermute/base/base_dynamic_buffer.cpp @@ -0,0 +1,192 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_dynamic_buffer.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBDynBuffer::CBDynBuffer(CBGame *inGame, uint32 initSize, uint32 growBy): CBBase(inGame) { + _buffer = NULL; + _size = 0; + _realSize = 0; + + _offset = 0; + _initSize = initSize; + _growBy = growBy; + + _initialized = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBDynBuffer::~CBDynBuffer() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::cleanup() { + if (_buffer) free(_buffer); + _buffer = NULL; + _size = 0; + _realSize = 0; + _offset = 0; + _initialized = false; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBDynBuffer::getSize() { + return _size; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBDynBuffer::init(uint32 initSize) { + cleanup(); + + if (initSize == 0) initSize = _initSize; + + _buffer = (byte *)malloc(initSize); + if (!_buffer) { + _gameRef->LOG(0, "CBDynBuffer::Init - Error allocating %d bytes", initSize); + return STATUS_FAILED; + } + + _realSize = initSize; + _initialized = true; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBDynBuffer::putBytes(byte *buffer, uint32 size) { + if (!_initialized) init(); + + while (_offset + size > _realSize) { + _realSize += _growBy; + _buffer = (byte *)realloc(_buffer, _realSize); + if (!_buffer) { + _gameRef->LOG(0, "CBDynBuffer::PutBytes - Error reallocating buffer to %d bytes", _realSize); + return STATUS_FAILED; + } + } + + memcpy(_buffer + _offset, buffer, size); + _offset += size; + _size += size; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBDynBuffer::getBytes(byte *buffer, uint32 size) { + if (!_initialized) init(); + + if (_offset + size > _size) { + _gameRef->LOG(0, "CBDynBuffer::GetBytes - Buffer underflow"); + return STATUS_FAILED; + } + + memcpy(buffer, _buffer + _offset, size); + _offset += size; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::putDWORD(uint32 val) { + putBytes((byte *)&val, sizeof(uint32)); +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBDynBuffer::getDWORD() { + uint32 ret; + getBytes((byte *)&ret, sizeof(uint32)); + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::putString(const char *val) { + if (!val) putString("(null)"); + else { + putDWORD(strlen(val) + 1); + putBytes((byte *)val, strlen(val) + 1); + } +} + + +////////////////////////////////////////////////////////////////////////// +char *CBDynBuffer::getString() { + uint32 len = getDWORD(); + char *ret = (char *)(_buffer + _offset); + _offset += len; + + if (!strcmp(ret, "(null)")) return NULL; + else return ret; +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::putText(const char *fmt, ...) { + va_list va; + + va_start(va, fmt); + putTextForm(fmt, va); + va_end(va); + +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::putTextIndent(int indent, const char *fmt, ...) { + va_list va; + + putText("%*s", indent, ""); + + va_start(va, fmt); + putTextForm(fmt, va); + va_end(va); +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::putTextForm(const char *format, va_list argptr) { + char buff[32768]; + vsprintf(buff, format, argptr); + putBytes((byte *)buff, strlen(buff)); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_dynamic_buffer.h b/engines/wintermute/base/base_dynamic_buffer.h new file mode 100644 index 0000000000..5795fe5bd1 --- /dev/null +++ b/engines/wintermute/base/base_dynamic_buffer.h @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BDYNBUFFER_H +#define WINTERMUTE_BDYNBUFFER_H + + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBDynBuffer : public CBBase { +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(byte *buffer, uint32 size); + uint32 getSize(); + bool init(uint32 initSize = 0); + void cleanup(); + uint32 _size; + byte *_buffer; + CBDynBuffer(CBGame *inGame, uint32 initSize = 1000, uint32 growBy = 1000); + virtual ~CBDynBuffer(); + +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 new file mode 100644 index 0000000000..712f64eb6f --- /dev/null +++ b/engines/wintermute/base/base_fader.cpp @@ -0,0 +1,176 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_Fader.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/util.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFader, false) + +////////////////////////////////////////////////////////////////////////// +CBFader::CBFader(CBGame *inGame): CBObject(inGame) { + _active = false; + _red = _green = _blue = 0; + _currentAlpha = 0x00; + _sourceAlpha = 0; + _targetAlpha = 0; + _duration = 1000; + _startTime = 0; + _system = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBFader::~CBFader() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFader::update() { + if (!_active) return STATUS_OK; + + int alphaDelta = _targetAlpha - _sourceAlpha; + + uint32 time; + + if (_system) time = CBPlatform::getTime() - _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 CBFader::display() { + if (!_active) return STATUS_OK; + + if (_currentAlpha > 0x00) return _gameRef->_renderer->fadeToColor(BYTETORGBA(_red, _green, _blue, _currentAlpha)); + else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFader::deactivate() { + _active = false; + _ready = true; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFader::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 = CBPlatform::getTime(); + else _startTime = _gameRef->_timer; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFader::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 = CBPlatform::getTime(); + else _startTime = _gameRef->_timer; + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBFader::getCurrentColor() { + return BYTETORGBA(_red, _green, _blue, _currentAlpha); +} + + + +////////////////////////////////////////////////////////////////////////// +bool CBFader::persist(CBPersistMgr *persistMgr) { + CBObject::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->_saving) _startTime = 0; + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_fader.h b/engines/wintermute/base/base_fader.h new file mode 100644 index 0000000000..679f5d0903 --- /dev/null +++ b/engines/wintermute/base/base_fader.h @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFADER_H +#define WINTERMUTE_BFADER_H + + +#include "engines/wintermute/base/base_object.h" + +namespace WinterMute { + +class CBFader : public CBObject { +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(CBFader, CBObject) + CBFader(CBGame *inGame); + virtual ~CBFader(); + bool _active; + byte _red; + byte _green; + byte _blue; + byte _currentAlpha; + byte _targetAlpha; + byte _sourceAlpha; + uint32 _duration; + uint32 _startTime; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp new file mode 100644 index 0000000000..1cb0464a1f --- /dev/null +++ b/engines/wintermute/base/base_file_manager.cpp @@ -0,0 +1,737 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/utils/string_util.h" +#include "engines/wintermute/utils/path_util.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_file_entry.h" +#include "engines/wintermute/base/file/base_package.h" +#include "engines/wintermute/base/file/BPkgFile.h" +#include "engines/wintermute/base/file/base_resources.h" +#include "engines/wintermute/base/base_registry.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/dcpackage.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/wintermute.h" +#include "common/str.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" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +CBFileManager::CBFileManager(CBGame *inGame): CBBase(inGame) { + _basePath = NULL; + + initPaths(); + registerPackages(); +} + + +////////////////////////////////////////////////////////////////////// +CBFileManager::~CBFileManager() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::cleanup() { + // delete registered paths + for (uint32 i = 0; i < _singlePaths.size(); i++) + delete [] _singlePaths[i]; + _singlePaths.clear(); + + for (uint32 i = 0; i < _packagePaths.size(); i++) + delete [] _packagePaths[i]; + _packagePaths.clear(); + + + // delete file entries + _filesIter = _files.begin(); + while (_filesIter != _files.end()) { + delete _filesIter->_value; + _filesIter++; + } + _files.clear(); + + // close open files + for (uint32 i = 0; i < _openFiles.size(); i++) { + delete _openFiles[i]; + } + _openFiles.clear(); + + + // delete packages + for (uint32 i = 0; i < _packages.size(); i++) + delete _packages[i]; + _packages.clear(); + + delete[] _basePath; + _basePath = NULL; + + return STATUS_OK; +} + + + +#define MAX_FILE_SIZE 10000000 +////////////////////////////////////////////////////////////////////// +byte *CBFileManager::readWholeFile(const Common::String &filename, uint32 *size, bool mustExist) { + byte *buffer = NULL; + + Common::SeekableReadStream *file = openFile(filename); + if (!file) { + if (mustExist) _gameRef->LOG(0, "Error opening file '%s'", filename.c_str()); + return NULL; + } + + /* + if (File->GetSize() > MAX_FILE_SIZE) { + _gameRef->LOG(0, "File '%s' exceeds the maximum size limit (%d bytes)", Filename, MAX_FILE_SIZE); + CloseFile(File); + return NULL; + } + */ + + + buffer = new byte[file->size() + 1]; + if (buffer == NULL) { + _gameRef->LOG(0, "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()) { + _gameRef->LOG(0, "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; +} + +Common::SeekableReadStream *CBFileManager::loadSaveGame(const Common::String &filename) { + Common::SaveFileManager *saveMan = g_wintermute->getSaveFileMan(); + Common::InSaveFile *file = saveMan->openForLoading(filename); + return file; +} + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::saveFile(const Common::String &filename, byte *buffer, uint32 bufferSize, bool compressed, byte *prefixBuffer, uint32 prefixSize) { + // TODO + warning("Implement SaveFile"); + + Common::SaveFileManager *saveMan = g_wintermute->getSaveFileMan(); + Common::OutSaveFile *file = saveMan->openForSaving(filename); + file->write(prefixBuffer, prefixSize); + file->write(buffer, bufferSize); + file->finalize(); + delete file; +#if 0 + RestoreCurrentDir(); + + CBUtils::CreatePath(filename, false); + + FILE *f = fopen(filename, "wb"); + if (!f) { + _gameRef->LOG(0, "Error opening file '%s' for writing.", filename); + return STATUS_FAILED; + } + + if (PrefixBuffer && PrefixSize) { + fwrite(PrefixBuffer, PrefixSize, 1, f); + } + + if (Compressed) { + uint32 CompSize = BufferSize + (BufferSize / 100) + 12; // 1% extra space + byte *CompBuffer = new byte[CompSize]; + if (!CompBuffer) { + _gameRef->LOG(0, "Error allocating compression buffer while saving '%s'", filename); + Compressed = false; + } else { + if (compress(CompBuffer, (uLongf *)&CompSize, Buffer, BufferSize) == Z_OK) { + uint32 magic = DCGF_MAGIC; + fwrite(&magic, sizeof(uint32), 1, f); + magic = COMPRESSED_FILE_MAGIC; + fwrite(&magic, sizeof(uint32), 1, f); + + uint32 DataOffset = 5 * sizeof(uint32); + fwrite(&DataOffset, sizeof(uint32), 1, f); + + fwrite(&CompSize, sizeof(uint32), 1, f); + fwrite(&BufferSize, sizeof(uint32), 1, f); + + fwrite(CompBuffer, CompSize, 1, f); + } else { + _gameRef->LOG(0, "Error compressing data while saving '%s'", filename); + Compressed = false; + } + + delete [] CompBuffer; + } + } + + if (!Compressed) fwrite(Buffer, BufferSize, 1, f); + + fclose(f); +#endif + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::requestCD(int cd, char *packageFile, const char *filename) { + // unmount all non-local packages + for (uint32 i = 0; i < _packages.size(); i++) { + if (_packages[i]->_cD > 0) _packages[i]->close(); + } + + + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::addPath(TPathType type, const Common::String &path) { + if (path.c_str() == NULL || strlen(path.c_str()) < 1) return STATUS_FAILED; + + bool slashed = (path[path.size() - 1] == '\\' || path[path.size() - 1] == '/'); + + char *buffer = new char [strlen(path.c_str()) + 1 + (slashed ? 0 : 1)]; + if (buffer == NULL) return STATUS_FAILED; + + strcpy(buffer, path.c_str()); + if (!slashed) strcat(buffer, "\\"); + //CBPlatform::strlwr(buffer); + + switch (type) { + case PATH_SINGLE: + _singlePaths.push_back(buffer); + break; + case PATH_PACKAGE: + _packagePaths.push_back(buffer); + break; + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::reloadPaths() { + // delete registered paths + for (uint32 i = 0; i < _singlePaths.size(); i++) + delete [] _singlePaths[i]; + _singlePaths.clear(); + + for (uint32 i = 0; i < _packagePaths.size(); i++) + delete [] _packagePaths[i]; + _packagePaths.clear(); + + return initPaths(); +} + + +#define TEMP_BUFFER_SIZE 32768 +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::initPaths() { + restoreCurrentDir(); + + AnsiString pathList; + int numPaths; + + // single files paths + pathList = _gameRef->_registry->readString("Resource", "CustomPaths", ""); + numPaths = CBUtils::strNumEntries(pathList.c_str(), ';'); + + for (int i = 0; i < numPaths; i++) { + char *path = CBUtils::strEntry(i, pathList.c_str(), ';'); + if (path && strlen(path) > 0) { + addPath(PATH_SINGLE, path); + } + delete[] path; + path = NULL; + } + addPath(PATH_SINGLE, ".\\"); + + + // package files paths + addPath(PATH_PACKAGE, "./"); + + pathList = _gameRef->_registry->readString("Resource", "PackagePaths", ""); + numPaths = CBUtils::strNumEntries(pathList.c_str(), ';'); + + for (int i = 0; i < numPaths; i++) { + char *path = CBUtils::strEntry(i, pathList.c_str(), ';'); + if (path && strlen(path) > 0) { + addPath(PATH_PACKAGE, path); + } + delete[] path; + path = NULL; + } + addPath(PATH_PACKAGE, "data"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::registerPackages() { + restoreCurrentDir(); + + _gameRef->LOG(0, "Scanning packages..."); + debugC(kWinterMuteDebugFileAccess, "Scanning packages"); + + Common::ArchiveMemberList files; + SearchMan.listMatchingMembers(files, "*.dcp"); + + for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); it++) { + registerPackage((*it)->getName().c_str()); + } +#if 0 + AnsiString extension = AnsiString(PACKAGE_EXTENSION); + + for (int i = 0; i < _packagePaths.getSize(); i++) { + boost::filesystem::path absPath = boost::filesystem::syste_complete(_packagePaths[i]); + + //_gameRef->LOG(0, "Scanning: %s", absPath.string().c_str()); + //printf("Scanning: %s\n", absPath.string().c_str()); + + if (!exists(absPath)) continue; + + // scan files + boost::filesystem::directory_iterator endIter; + for (boost::filesystem::directory_iterator dit(absPath); dit != endIter; ++dit) { + if (!is_directory((*dit).status())) { + AnsiString fileName = (*dit).path().string(); + + if (!IsValidPackage(fileName)) continue; + + warning("%s", fileName.c_str()); + //printf("%s\n", fileName.c_str()); + if (!StringUtil::CompareNoCase(extension, PathUtil::GetExtension(fileName))) continue; + warning("Registered"); + RegisterPackage(absPath.string().c_str(), dit->path().filename().string().c_str()); + } + } + } +#endif + debugC(kWinterMuteDebugFileAccess, " Registered %d files in %d package(s)", _files.size(), _packages.size()); + _gameRef->LOG(0, " Registered %d files in %d package(s)", _files.size(), _packages.size()); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::registerPackage(const Common::String &filename , bool searchSignature) { +// FILE *f = fopen(filename, "rb"); + Common::File *package = new Common::File(); + package->open(filename); + if (!package->isOpen()) { + _gameRef->LOG(0, " Error opening package file '%s'. Ignoring.", filename.c_str()); + return STATUS_OK; + } + + uint32 absoluteOffset = 0; + bool boundToExe = false; + + if (searchSignature) { + uint32 offset; + if (!findPackageSignature(package, &offset)) { + delete package; + return STATUS_OK; + } else { + package->seek(offset, SEEK_SET); + absoluteOffset = offset; + boundToExe = true; + } + } + + TPackageHeader hdr; + hdr.readFromStream(package); +// package->read(&hdr, sizeof(TPackageHeader), 1, f); + if (hdr.Magic1 != PACKAGE_MAGIC_1 || hdr.Magic2 != PACKAGE_MAGIC_2 || hdr.PackageVersion > PACKAGE_VERSION) { + _gameRef->LOG(0, " Invalid header in package file '%s'. Ignoring.", filename.c_str()); + delete package; + return STATUS_OK; + } + + if (hdr.PackageVersion != PACKAGE_VERSION) { + _gameRef->LOG(0, " Warning: package file '%s' is outdated.", filename.c_str()); + } + + // new in v2 + if (hdr.PackageVersion == PACKAGE_VERSION) { + uint32 dirOffset; + dirOffset = package->readUint32LE(); + dirOffset += absoluteOffset; + package->seek(dirOffset, SEEK_SET); + } + + for (uint32 i = 0; i < hdr.NumDirs; i++) { + CBPackage *pkg = new CBPackage(_gameRef); + if (!pkg) return STATUS_FAILED; + + pkg->_boundToExe = boundToExe; + + // read package info + byte nameLength = package->readByte(); + pkg->_name = new char[nameLength]; + package->read(pkg->_name, nameLength); + pkg->_cD = package->readByte(); + pkg->_priority = hdr.Priority; + + if (!hdr.MasterIndex) pkg->_cD = 0; // override CD to fixed disk + _packages.push_back(pkg); + + + // read file entries + uint32 NumFiles = package->readUint32LE(); + + for (uint32 j = 0; j < NumFiles; j++) { + char *name; + uint32 offset, length, compLength, flags, timeDate1, timeDate2; + + nameLength = package->readByte(); + name = new char[nameLength]; + package->read(name, nameLength); + + // v2 - xor name + if (hdr.PackageVersion == PACKAGE_VERSION) { + for (int k = 0; k < nameLength; k++) { + ((byte *)name)[k] ^= 'D'; + } + } + + // some old version of ProjectMan writes invalid directory entries + // so at least prevent strupr from corrupting memory + name[nameLength - 1] = '\0'; + + + CBPlatform::strupr(name); + + offset = package->readUint32LE(); + offset += absoluteOffset; + length = package->readUint32LE(); + compLength = package->readUint32LE(); + flags = package->readUint32LE(); + + if (hdr.PackageVersion == PACKAGE_VERSION) { + timeDate1 = package->readUint32LE(); + timeDate2 = package->readUint32LE(); + } + _filesIter = _files.find(name); + if (_filesIter == _files.end()) { + CBFileEntry *file = new CBFileEntry(_gameRef); + file->_package = pkg; + file->_offset = offset; + file->_length = length; + file->_compressedLength = compLength; + file->_flags = flags; + + _files[name] = file; + } else { + // current package has lower CD number or higher priority, than the registered + if (pkg->_cD < _filesIter->_value->_package->_cD || pkg->_priority > _filesIter->_value->_package->_priority) { + _filesIter->_value->_package = pkg; + _filesIter->_value->_offset = offset; + _filesIter->_value->_length = length; + _filesIter->_value->_compressedLength = compLength; + _filesIter->_value->_flags = flags; + } + } + delete [] name; + } + } + + + delete package; + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::isValidPackage(const AnsiString &fileName) const { + AnsiString plainName = PathUtil::getFileNameWithoutExtension(fileName); + + // check for device-type specific packages + if (StringUtil::startsWith(plainName, "xdevice_", true)) { + return StringUtil::compareNoCase(plainName, "xdevice_" + _gameRef->getDeviceType()); + } + return true; +} + +////////////////////////////////////////////////////////////////////////// +Common::File *CBFileManager::openPackage(const Common::String &name) { + //TODO: Is it really necessary to do this when we have the ScummVM-system? + + //RestoreCurrentDir(); + + Common::File *ret = new Common::File(); + char filename[MAX_PATH_LENGTH]; + + for (uint32 i = 0; i < _packagePaths.size(); i++) { + sprintf(filename, "%s%s.%s", _packagePaths[i], name.c_str(), PACKAGE_EXTENSION); + ret->open(filename); + if (ret->isOpen()) { + return ret; + } + } + + sprintf(filename, "%s.%s", name.c_str(), PACKAGE_EXTENSION); + ret->open(filename); + if (ret->isOpen()) { + return ret; + } + warning("CBFileManager::OpenPackage - Couldn't load file %s", name.c_str()); + delete ret; + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +Common::File *CBFileManager::openSingleFile(const Common::String &name) { + restoreCurrentDir(); + + Common::File *ret = NULL; + char filename[MAX_PATH_LENGTH]; + + for (uint32 i = 0; i < _singlePaths.size(); i++) { + sprintf(filename, "%s%s", _singlePaths[i], name.c_str()); + ret->open(filename); + if (ret->isOpen()) + return ret; + } + + // didn't find in search paths, try to open directly + ret->open(name); + if (ret->isOpen()) { + return ret; + } else { + delete ret; + return NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::getFullPath(const Common::String &filename, char *fullname) { + restoreCurrentDir(); + + Common::File f; + bool found = false; + + for (uint32 i = 0; i < _singlePaths.size(); i++) { + sprintf(fullname, "%s%s", _singlePaths[i], filename.c_str()); + f.open(fullname); + if (f.isOpen()) { + f.close(); + found = true; + break; + } + } + + if (!found) { + f.open(filename.c_str()); + if (f.isOpen()) { + f.close(); + found = true; + strcpy(fullname, filename.c_str()); + } + } + + return found; +} + + +////////////////////////////////////////////////////////////////////////// +CBFileEntry *CBFileManager::getPackageEntry(const Common::String &filename) { + char *upc_name = new char[strlen(filename.c_str()) + 1]; + strcpy(upc_name, filename.c_str()); + CBPlatform::strupr(upc_name); + + CBFileEntry *ret = NULL; + _filesIter = _files.find(upc_name); + if (_filesIter != _files.end()) ret = _filesIter->_value; + + delete [] upc_name; + + return ret; +} + +bool CBFileManager::hasFile(const Common::String &filename) { + //TODO: Do this in a much simpler fashion + Common::SeekableReadStream *stream = openFile(filename, true, false); + if (!stream) { + return false; + } + delete stream; + return true; +} + +////////////////////////////////////////////////////////////////////////// +Common::SeekableReadStream *CBFileManager::openFile(const Common::String &filename, bool absPathWarning, bool keepTrackOf) { + if (strcmp(filename.c_str(), "") == 0) return NULL; + //_gameRef->LOG(0, "open file: %s", filename); + /*#ifdef __WIN32__ + if (_gameRef->_debugDebugMode && _gameRef->_debugAbsolutePathWarning && AbsPathWarning) { + char Drive[_MAX_DRIVE]; + _splitpath(filename, Drive, NULL, NULL, NULL); + if (Drive[0] != '\0') { + _gameRef->LOG(0, "WARNING: Referencing absolute path '%s'. The game will NOT work on another computer.", filename); + } + } + #endif*/ + + Common::SeekableReadStream *file = openFileRaw(filename); + if (file && keepTrackOf) _openFiles.push_back(file); + return file; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::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 *CBFileManager::openFileRaw(const Common::String &filename) { + restoreCurrentDir(); + + Common::SeekableReadStream *ret = NULL; + + if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) { + CBSaveThumbFile *SaveThumbFile = new CBSaveThumbFile(_gameRef); + if (DID_SUCCEED(SaveThumbFile->open(filename))) { + ret = SaveThumbFile->getMemStream(); + } + delete SaveThumbFile; + return ret; + } + + + + ret = openDiskFile(filename, this); + if (ret) return ret; + + ret = openPkgFile(filename, this); + if (ret) return ret; + + ret = CBResources::getFile(filename); + if (ret) return ret; + + warning("BFileManager::OpenFileRaw - Failed to open %s", filename.c_str()); + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::restoreCurrentDir() { + if (!_basePath) return STATUS_OK; + else { + /*if (!chdir(_basePath)) return STATUS_OK; + else return STATUS_FAILED;*/ + warning("CBFileManager::RestoreCurrentDir - ignored"); + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::setBasePath(const Common::String &path) { + cleanup(); + + if (path.c_str()) { + _basePath = new char[path.size() + 1]; + strcpy(_basePath, path.c_str()); + } + + initPaths(); + registerPackages(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::findPackageSignature(Common::File *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; + +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h new file mode 100644 index 0000000000..1bf3156ebe --- /dev/null +++ b/engines/wintermute/base/base_file_manager.h @@ -0,0 +1,85 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFILEMANAGER_H +#define WINTERMUTE_BFILEMANAGER_H + +#include "engines/wintermute/base/file/base_file_entry.h" +#include "common/archive.h" +#include "common/str.h" + +namespace Common { +class File; +} + +namespace WinterMute { +class CBFile; +class CBFileManager: CBBase { +public: + bool findPackageSignature(Common::File *f, uint32 *offset); + bool cleanup(); + bool setBasePath(const Common::String &path); + bool restoreCurrentDir(); + char *_basePath; + bool getFullPath(const Common::String &filename, char *fullname); + Common::SeekableReadStream *openFileRaw(const Common::String &filename); + bool closeFile(Common::SeekableReadStream *File); + bool hasFile(const Common::String &filename); + Common::SeekableReadStream *openFile(const Common::String &filename, bool absPathWarning = true, bool keepTrackOf = true); + CBFileEntry *getPackageEntry(const Common::String &filename); + Common::File *openSingleFile(const Common::String &name); + Common::File *openPackage(const Common::String &name); + bool registerPackages(); + bool initPaths(); + bool reloadPaths(); + typedef enum { + PATH_PACKAGE, PATH_SINGLE + } TPathType; + bool addPath(TPathType type, const Common::String &path); + bool requestCD(int cd, char *packageFile, const char *filename); + Common::SeekableReadStream *loadSaveGame(const Common::String &filename); + bool saveFile(const Common::String &filename, byte *buffer, uint32 bufferSize, bool compressed = false, byte *prefixBuffer = NULL, uint32 prefixSize = 0); + byte *readWholeFile(const Common::String &filename, uint32 *size = NULL, bool mustExist = true); + CBFileManager(CBGame *inGame = NULL); + virtual ~CBFileManager(); + Common::Array _singlePaths; + Common::Array _packagePaths; + Common::Array _packages; + Common::Array _openFiles; + + Common::HashMap _files; +private: + bool registerPackage(const Common::String &filename, bool searchSignature = false); + Common::HashMap::iterator _filesIter; + bool isValidPackage(const AnsiString &fileName) const; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp new file mode 100644 index 0000000000..468ad29858 --- /dev/null +++ b/engines/wintermute/base/base_frame.cpp @@ -0,0 +1,705 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CBFrame, false) + +////////////////////////////////////////////////////////////////////// +CBFrame::CBFrame(CBGame *inGame): CBScriptable(inGame, true) { + _delay = 0; + _moveX = _moveY = 0; + + _sound = NULL; + _killSound = false; + + _editorExpanded = false; + _keyframe = false; +} + + +////////////////////////////////////////////////////////////////////// +CBFrame::~CBFrame() { + delete _sound; + _sound = NULL; + + for (int i = 0; i < _subframes.getSize(); i++) + delete _subframes[i]; + _subframes.removeAll(); + + for (int i = 0; i < _applyEvent.getSize(); i++) { + delete[] _applyEvent[i]; + _applyEvent[i] = NULL; + } + _applyEvent.removeAll(); +} + + +////////////////////////////////////////////////////////////////////// +bool CBFrame::draw(int x, int y, CBObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, bool allFrames, float rotate, TSpriteBlendMode blendMode) { + bool res; + + for (int i = 0; i < _subframes.getSize(); i++) { + res = _subframes[i]->draw(x, y, registerOwner, zoomX, zoomY, precise, alpha, rotate, blendMode); + if (DID_FAIL(res)) return res; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFrame::oneTimeDisplay(CBObject *owner, bool muted) { + if (_sound && !muted) { + if (owner) owner->updateOneSound(_sound); + _sound->play(); + /* + if (_gameRef->_state == GAME_FROZEN) { + _sound->Pause(true); + } + */ + } + if (owner) { + for (int i = 0; i < _applyEvent.getSize(); 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 CBFrame::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; + CBParser parser(_gameRef); + 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; + CBPlatform::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: { + CBSubFrame *subframe = new CBSubFrame(_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 CBSound(_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; + } + + + CBSubFrame *sub = new CBSubFrame(_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 (CBPlatform::isRectEmpty(&rect)) sub->setDefaultRect(); + else sub->_rect = 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.insertAt(0, sub); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFrame::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float scaleY) { + if (!rect) return false; + CBPlatform::setRectEmpty(rect); + + Rect32 subRect; + + for (int i = 0; i < _subframes.getSize(); i++) { + _subframes[i]->getBoundingRect(&subRect, x, y, scaleX, scaleY); + CBPlatform::unionRect(rect, rect, &subRect); + } + return true; +} + + + +////////////////////////////////////////////////////////////////////////// +bool CBFrame::saveAsText(CBDynBuffer *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->_soundFilename) + buffer->putTextIndent(indent + 2, "SOUND=\"%s\"\n", _sound->_soundFilename); + + 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.getSize() > 0) _subframes[0]->saveAsText(buffer, indent, false); + + for (int i = 1; i < _subframes.getSize(); i++) { + _subframes[i]->saveAsText(buffer, indent + 2); + } + + for (int i = 0; i < _applyEvent.getSize(); i++) { + buffer->putTextIndent(indent + 2, "APPLY_EVENT=\"%s\"\n", _applyEvent[i]); + } + + CBBase::saveAsText(buffer, indent + 2); + + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFrame::persist(CBPersistMgr *persistMgr) { + CBScriptable::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 CBFrame::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + + ////////////////////////////////////////////////////////////////////////// + // GetSound + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetSound") == 0) { + stack->correctParams(0); + + if (_sound && _sound->_soundFilename) stack->pushString(_sound->_soundFilename); + else stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetSound + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetSound") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + delete _sound; + _sound = NULL; + + if (!val->isNULL()) { + _sound = new CBSound(_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 >= _subframes.getSize()) { + 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); + CScValue *val = stack->pop(); + if (val->isInt()) { + int index = val->getInt(-1); + if (index < 0 || index >= _subframes.getSize()) { + script->runtimeError("Frame.DeleteSubframe: Subframe index %d is out of range.", index); + } + } else { + CBSubFrame *sub = (CBSubFrame *)val->getNative(); + for (int i = 0; i < _subframes.getSize(); i++) { + if (_subframes[i] == sub) { + delete _subframes[i]; + _subframes.removeAt(i); + break; + } + } + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddSubframe + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddSubframe") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + const char *filename = NULL; + if (!val->isNULL()) filename = val->getString(); + + CBSubFrame *sub = new CBSubFrame(_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; + + CScValue *val = stack->pop(); + const char *filename = NULL; + if (!val->isNULL()) filename = val->getString(); + + CBSubFrame *sub = new CBSubFrame(_gameRef); + if (filename != NULL) { + sub->setSurface(filename); + } + + if (index >= _subframes.getSize()) _subframes.add(sub); + else _subframes.insertAt(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 >= _applyEvent.getSize()) { + 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 (int i = 0; i < _applyEvent.getSize(); 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 (int i = 0; i < _applyEvent.getSize(); i++) { + if (scumm_stricmp(_applyEvent[i], event) == 0) { + delete [] _applyEvent[i]; + _applyEvent.removeAt(i); + break; + } + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + else { + if (_subframes.getSize() == 1) return _subframes[0]->scCallMethod(script, stack, thisStack, name); + else return CBScriptable::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBFrame::scGetProperty(const char *name) { + if (!_scValue) _scValue = new CScValue(_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.getSize()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumEvents (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumEvents") == 0) { + _scValue->setInt(_applyEvent.getSize()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + else { + if (_subframes.getSize() == 1) return _subframes[0]->scGetProperty(name); + else return CBScriptable::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFrame::scSetProperty(const char *name, CScValue *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.getSize() == 1) return _subframes[0]->scSetProperty(name, value); + else return CBScriptable::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBFrame::scToString() { + return "[frame]"; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h new file mode 100644 index 0000000000..f3dec4e16f --- /dev/null +++ b/engines/wintermute/base/base_frame.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFRAME_H +#define WINTERMUTE_BFRAME_H + +#include "engines/wintermute/base/base_scriptable.h" +#include "engines/wintermute/coll_templ.h" + +namespace WinterMute { +class CBSound; +class CBSubFrame; +class CBObject; +class CScScript; +class CScStack; +class CBFrame: public CBScriptable { +public: + bool _killSound; + bool _keyframe; + bool oneTimeDisplay(CBObject *owner, bool muted = false); + DECLARE_PERSISTENT(CBFrame, CBScriptable) + CBSound *_sound; + bool _editorExpanded; + bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100); + bool saveAsText(CBDynBuffer *buffer, int indent); + int _moveY; + int _moveX; + uint32 _delay; + CBArray _subframes; + bool draw(int x, int y, CBObject *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); + + CBFrame(CBGame *inGame); + virtual ~CBFrame(); + + CBArray _applyEvent; + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp new file mode 100644 index 0000000000..d5e9c99dcf --- /dev/null +++ b/engines/wintermute/base/base_game.cpp @@ -0,0 +1,4477 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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/base_registry.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/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/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/wintermute.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(CBGame, true) + + +////////////////////////////////////////////////////////////////////// +CBGame::CBGame(): CBObject(this) { + _shuttingDown = false; + + _state = GAME_RUNNING; + _origState = GAME_RUNNING; + _freezeLevel = 0; + + _interactive = true; + _origInteractive = false; + + _surfaceStorage = NULL; + _fontStorage = NULL; + _renderer = NULL; + _soundMgr = NULL; + _fileManager = NULL; + _transMgr = NULL; + _debugMgr = NULL; + _scEngine = NULL; + _keyboardState = NULL; + + _mathClass = NULL; + + _debugLogFile = NULL; + _debugDebugMode = false; + _debugAbsolutePathWarning = true; + _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; + + _registry = new CBRegistry(this); + _stringTable = new CBStringTable(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; + + _indicatorDisplay = false; + _indicatorColor = BYTETORGBA(255, 0, 0, 128); + _indicatorProgress = 0; + _indicatorX = -1; + _indicatorY = -1; + _indicatorWidth = -1; + _indicatorHeight = 8; + _richSavedGames = false; + _savedGameExt = NULL; + CBUtils::setString(&_savedGameExt, "dsv"); + + _musicCrossfadeRunning = false; + _musicCrossfadeStartTime = 0; + _musicCrossfadeLength = 0; + _musicCrossfadeChannel1 = -1; + _musicCrossfadeChannel2 = -1; + _musicCrossfadeSwap = false; + + _loadImageName = NULL; + _saveImageName = NULL; + _saveLoadImage = NULL; + + _saveImageX = _saveImageY = 0; + _loadImageX = _loadImageY = 0; + + _localSaveDir = NULL; + CBUtils::setString(&_localSaveDir, "saves"); + _saveDirChecked = false; + + _loadingIcon = NULL; + _loadingIconX = _loadingIconY = 0; + _loadingIconPersistent = false; + + _textEncoding = TEXT_ANSI; + _textRTL = false; + + _soundBufferSizeSec = 3; + _suspendedRendering = false; + + _lastCursor = NULL; + + + CBPlatform::setRectEmpty(&_mouseLockRect); + + _suppressScriptErrors = false; + _lastMiniUpdate = 0; + _miniUpdateEnabled = false; + + _cachedThumbnail = NULL; + + _autorunDisabled = false; + + // compatibility bits + _compatKillMethodThreads = false; + + _usedMem = 0; + + + _autoSaveOnExit = true; + _autoSaveSlot = 999; + _cursorHidden = false; + +/*#ifdef __IPHONEOS__ + _touchInterface = true; + _constrainedMemory = true; // TODO differentiate old and new iOS devices +#else*/ + _touchInterface = false; + _constrainedMemory = false; +//#endif + +} + + +////////////////////////////////////////////////////////////////////// +CBGame::~CBGame() { + _shuttingDown = true; + + LOG(0, ""); + LOG(0, "Shutting down..."); + + getDebugMgr()->onGameShutdown(); + + _registry->writeBool("System", "LastRun", true); + + cleanup(); + + delete[] _localSaveDir; + delete[] _settingsGameFile; + delete[] _savedGameExt; + + delete _cachedThumbnail; + + delete _saveLoadImage; + delete _mathClass; + + delete _transMgr; + delete _scEngine; + delete _fontStorage; + delete _surfaceStorage; + delete _videoPlayer; + delete _theoraPlayer; + delete _soundMgr; + delete _debugMgr; + //SAFE_DELETE(_keyboardState); + + delete _renderer; + delete _fileManager; + delete _registry; + delete _stringTable; + + _localSaveDir = NULL; + _settingsGameFile = NULL; + _savedGameExt = NULL; + + _cachedThumbnail = NULL; + + _saveLoadImage = NULL; + _mathClass = NULL; + + _transMgr = NULL; + _scEngine = NULL; + _fontStorage = NULL; + _surfaceStorage = NULL; + _videoPlayer = NULL; + _theoraPlayer = NULL; + _soundMgr = NULL; + _debugMgr = NULL; + + _renderer = NULL; + _fileManager = NULL; + _registry = NULL; + _stringTable = NULL; + + DEBUG_DebugDisable(); + CBPlatform::outputDebugString("--- shutting down normally ---\n"); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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 (int i = 0; i < _regObjects.getSize(); i++) { + delete _regObjects[i]; + _regObjects[i] = NULL; + } + _regObjects.removeAll(); + + _windows.removeAll(); // refs only + _focusedWindow = NULL; // ref only + + delete[] _saveImageName; + delete[] _loadImageName; + _saveImageName = NULL; + _loadImageName = NULL; + + delete _cursorNoninteractive; + delete _cursor; + delete _activeCursor; + _cursorNoninteractive = NULL; + _cursor = NULL; + _activeCursor = NULL; + + delete _scValue; + delete _sFX; + _scValue = NULL; + _sFX = NULL; + + for (int i = 0; i < _scripts.getSize(); i++) { + _scripts[i]->_owner = NULL; + _scripts[i]->finish(); + } + _scripts.removeAll(); + + _fontStorage->removeFont(_systemFont); + _systemFont = NULL; + + _fontStorage->removeFont(_videoFont); + _videoFont = NULL; + + for (int i = 0; i < _quickMessages.getSize(); i++) delete _quickMessages[i]; + _quickMessages.removeAll(); + + _viewportStack.removeAll(); + _viewportSP = -1; + + delete[] _name; + delete[] _filename; + _name = NULL; + _filename = NULL; + for (int i = 0; i < 7; i++) { + delete[] _caption[i]; + _caption[i] = NULL; + } + + _lastCursor = NULL; + + delete _keyboardState; + _keyboardState = NULL; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +bool CBGame::initialize1() { + bool loaded = false; // Not really a loop, but a goto-replacement. + while (!loaded) { + _surfaceStorage = new CBSurfaceStorage(this); + if (_surfaceStorage == NULL) + break; + + _fontStorage = new CBFontStorage(this); + if (_fontStorage == NULL) + break; + + _fileManager = new CBFileManager(this); + if (_fileManager == NULL) + break; + + _soundMgr = new CBSoundMgr(this); + if (_soundMgr == NULL) + break; + + _debugMgr = new CBDebugger(this); + if (_debugMgr == NULL) + break; + + _mathClass = new CSXMath(this); + if (_mathClass == NULL) + break; + + _scEngine = new CScEngine(this); + if (_scEngine == NULL) + break; + + _videoPlayer = new CVidPlayer(this); + if (_videoPlayer == NULL) + break; + + _transMgr = new CBTransitionMgr(this); + if (_transMgr == NULL) + break; + + _keyboardState = new CBKeyboardState(this); + if (_keyboardState == NULL) + break; + + _fader = new CBFader(this); + if (_fader == NULL) + break; + registerObject(_fader); + + loaded = true; + } + if (loaded == true) { + return STATUS_OK; + } else { + delete _mathClass; + delete _keyboardState; + delete _transMgr; + delete _debugMgr; + delete _surfaceStorage; + delete _fontStorage; + delete _soundMgr; + delete _fileManager; + delete _scEngine; + delete _videoPlayer; + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////// +bool CBGame::initialize2() { // we know whether we are going to be accelerated + _renderer = makeOSystemRenderer(this); + if (_renderer == NULL) return STATUS_FAILED; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +bool CBGame::initialize3() { // renderer is initialized + _posX = _renderer->_width / 2; + _posY = _renderer->_height / 2; + + if (_indicatorY == -1) _indicatorY = _renderer->_height - _indicatorHeight; + if (_indicatorX == -1) _indicatorX = 0; + if (_indicatorWidth == -1) _indicatorWidth = _renderer->_width; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +void CBGame::DEBUG_DebugEnable(const char *filename) { + _debugDebugMode = true; + + /* time_t timeNow; + time(&timeNow); + struct tm *tm = localtime(&timeNow); + + #ifdef _DEBUG + LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%04d (Debug Build) *******************", tm->tm_mday, tm->tm_mon, tm->tm_year + 1900); + #else + LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%04d (Release Build) *****************", tm->tm_mday, tm->tm_mon, tm->tm_year + 1900); + #endif*/ + 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); + //LOG(0, "Extensions: %s ver %d.%02d", EXT_NAME, EXT_VER_MAJOR, EXT_VER_MINOR); + + AnsiString platform = CBPlatform::getPlatformName(); + LOG(0, "Platform: %s", platform.c_str()); + LOG(0, ""); +} + + +////////////////////////////////////////////////////////////////////// +void CBGame::DEBUG_DebugDisable() { + if (_debugLogFile != NULL) { + LOG(0, "********** DEBUG LOG CLOSED ********************************************"); + //fclose((FILE *)_debugLogFile); + _debugLogFile = NULL; + } + _debugDebugMode = false; +} + + +////////////////////////////////////////////////////////////////////// +void CBGame::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); + } + if (_debugMgr) _debugMgr->onLog(res, buff); + + 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 CBGame::setEngineLogCallback(ENGINE_LOG_CALLBACK callback, void *data) { + _engineLogCallback = callback; + _engineLogCallbackData = data; +} + + +////////////////////////////////////////////////////////////////////// +bool CBGame::initLoop() { + _viewportSP = -1; + + _currentTime = CBPlatform::getTime(); + + getDebugMgr()->onGameTick(); + _renderer->initLoop(); + _soundMgr->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.getSize() - 1; i >= 0; i--) { + if (_windows[i]->_visible) { + _focusedWindow = _windows[i]; + break; + } + } + + updateSounds(); + + if (_fader) _fader->update(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +bool CBGame::initInput() { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBGame::getSequence() { + return ++_sequence; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::setOffset(int offsetX, int offsetY) { + _offsetX = offsetX; + _offsetY = offsetY; +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::getOffset(int *offsetX, int *offsetY) { + if (offsetX != NULL) *offsetX = _offsetX; + if (offsetY != NULL) *offsetY = _offsetY; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CBGame::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CBGame::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 + + byte *params; + int cmd; + CBParser parser(_gameRef); + + 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 CBSprite(_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 CBSprite(_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 CBSprite(_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: + CBUtils::setString(&_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: + CBUtils::setString(&_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: + CBUtils::setString(&_localSaveDir, (char *)params); + break; + + case TOKEN_COMPAT_KILL_METHOD_THREADS: + parser.scanStr((char *)params, "%b", &_compatKillMethodThreads); + break; + } + } + + 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 CBGame::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 = CBObject::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(); + CScValue *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); + CBScriptable *obj = stack->pop()->getNative(); + if (validObject((CBObject *) 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); + CScValue *val = stack->pop(); + CBObject *obj = (CBObject *)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); + CUIWindow *win = new CUIWindow(_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); + CScValue *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(); + CScValue *valLooping = stack->pop(); + bool looping = valLooping->isNULL() ? true : valLooping->getBool(); + + CScValue *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]->_soundFilename) stack->pushNULL(); + else stack->pushString(_music[channel]->_soundFilename); + } + 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(); + + CBSound *sound = new CBSound(_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; + + CBPlatform::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) CBUtils::swap(&left, &right); + if (bottom < top) CBUtils::swap(&top, &bottom); + + CBPlatform::setRect(&_mouseLockRect, left, top, right, bottom); + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PlayVideo + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PlayVideo") == 0) { + /* stack->correctParams(0); + stack->pushBool(false); + + return STATUS_OK; + // TODO: ADDVIDEO + */ + + _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); + CScValue *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); + + CScValue *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(0); + stack->pushBool(false); + + return STATUS_OK;*/ + // TODO: ADDVIDEO + + stack->correctParams(7); + const char *filename = stack->pop()->getString(); + CScValue *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); + + CScValue *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 CVidTheoraPlayer(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(); + _registry->writeInt("PrivateSettings", key, 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(); + stack->pushInt(_registry->readInt("PrivateSettings", key, initVal)); + 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(); + _registry->writeString("PrivateSettings", key, val); + 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(); + AnsiString val = _registry->readString("PrivateSettings", key, initVal); + stack->pushString(val.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(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'; + getSaveSlotDescription(slot, desc); + stack->pushString(desc); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // EmptySaveSlot + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "EmptySaveSlot") == 0) { + stack->correctParams(1); + int slot = stack->pop()->getInt(); + 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->_filename) stack->pushNULL(); + else stack->pushString(_activeCursor->_filename); + + 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(); + + // TODO: Replace with fileExists + Common::SeekableReadStream *file = _fileManager->openFile(filename, false); + if (!file) stack->pushBool(false); + else { + _fileManager->closeFile(file); + stack->pushBool(true); + } + 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]; + + CScValue *Val = stack->pop(); + + warning("BGame::ScCallMethod - Screenshot not reimplemented"); //TODO + int fileNum = 0; + + while (true) { + sprintf(filename, "%s%03d.bmp", Val->isNULL() ? _name : Val->getString(), fileNum); + if (!Common::File::exists(filename)) + break; + fileNum++; + } + + bool ret = false; + CBImage *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; + CBImage *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); + CScValue *val = stack->pop(); + + CUIWindow *win = new CUIWindow(_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); + CBObject *obj = (CBObject *)stack->pop()->getNative(); + for (int i = 0; i < _windows.getSize(); 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); + CScValue *val = stack->pop(); + _loadImageX = stack->pop()->getInt(); + _loadImageY = stack->pop()->getInt(); + + if (val->isNULL()) { + delete[] _loadImageName; + _loadImageName = NULL; + } else { + CBUtils::setString(&_loadImageName, val->getString()); + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetSavingScreen + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetSavingScreen") == 0) { + stack->correctParams(3); + CScValue *val = stack->pop(); + _saveImageX = stack->pop()->getInt(); + _saveImageY = stack->pop()->getInt(); + + if (val->isNULL()) { + delete[] _saveImageName; + _saveImageName = NULL; + } else { + CBUtils::setString(&_saveImageName, val->getString()); + } + 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->_filename) stack->pushNULL(); + else stack->pushString(_cursorNoninteractive->_filename); + + 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 CBSprite(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 CBSaveThumbHelper(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 = _fileManager->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); + + _fileManager->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); +/*#ifdef __IPHONEOS__ + IOS_ShowStatusLine(TRUE); +#endif*/ + stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HideStatusLine + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "HideStatusLine") == 0) { + stack->correctParams(0); +/*#ifdef __IPHONEOS__ + IOS_ShowStatusLine(FALSE); +#endif*/ + stack->pushNULL(); + + return STATUS_OK; + } + + else return CBObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBGame::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(_name); + 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)CBPlatform::getTime()); + 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 = getDataDir(); + _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(CBPlatform::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) { + _scValue->setInt(_registry->readInt("System", "MostRecentSaveSlot", -1)); + 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 CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::scSetProperty(const char *name, CScValue *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 = CBObject::scSetProperty(name, value); + setWindowTitle(); + return res; + } + + ////////////////////////////////////////////////////////////////////////// + // MainObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MainObject") == 0) { + CBScriptable *obj = value->getNative(); + if (obj == NULL || validObject((CBObject *)obj)) _mainObject = (CBObject *)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 CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBGame::scToString() { + return "[game object]"; +} + + + +#define QUICK_MSG_DURATION 3000 +////////////////////////////////////////////////////////////////////////// +bool CBGame::displayQuickMsg() { + if (_quickMessages.getSize() == 0 || !_systemFont) return STATUS_OK; + + // update + for (int i = 0; i < _quickMessages.getSize(); i++) { + if (_currentTime - _quickMessages[i]->_startTime >= QUICK_MSG_DURATION) { + delete _quickMessages[i]; + _quickMessages.removeAt(i); + i--; + } + } + + int posY = 20; + + // display + for (int i = 0; i < _quickMessages.getSize(); 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 CBGame::quickMessage(const char *text) { + if (_quickMessages.getSize() >= MAX_QUICK_MSG) { + delete _quickMessages[0]; + _quickMessages.removeAt(0); + } + _quickMessages.add(new CBQuickMsg(_gameRef, text)); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::quickMessageForm(char *fmt, ...) { + char buff[256]; + va_list va; + + va_start(va, fmt); + vsprintf(buff, fmt, va); + va_end(va); + + quickMessage(buff); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::registerObject(CBObject *object) { + _regObjects.add(object); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::unregisterObject(CBObject *object) { + if (!object) return STATUS_OK; + + // is it a window? + for (int i = 0; i < _windows.getSize(); i++) { + if ((CBObject *)_windows[i] == object) { + _windows.removeAt(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 (int i = 0; i < _regObjects.getSize(); i++) { + if (_regObjects[i] == object) { + _regObjects.removeAt(i); + if (!_loadInProgress) CSysClassRegistry::getInstance()->enumInstances(invalidateValues, "CScValue", (void *)object); + delete object; + return STATUS_OK; + } + } + + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::invalidateValues(void *value, void *data) { + CScValue *val = (CScValue *)value; + if (val->isNative() && val->getNative() == data) { + if (!val->_persistent && ((CBScriptable *)data)->_refCount == 1) { + ((CBScriptable *)data)->_refCount++; + } + val->setNative(NULL); + val->setNULL(); + } +} + + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::validObject(CBObject *object) { + if (!object) return false; + if (object == this) return true; + + for (int i = 0; i < _regObjects.getSize(); i++) { + if (_regObjects[i] == object) return true; + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name) { + CScValue *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); + + CBScriptable *obj = stack->pop()->getNative(); + if (validObject((CBObject *)obj)) script->waitForExclusive((CBObject *)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(CBUtils::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; + CScValue *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(CBUtils::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; + CBUtils::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; + CBUtils::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; + CBUtils::RGBtoHSL(rgb, &H, &S, &L); + stack->pushInt(L); + } + + ////////////////////////////////////////////////////////////////////////// + // Debug + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Debug") == 0) { + stack->correctParams(0); + + if (_gameRef->getDebugMgr()->_enabled) { + _gameRef->getDebugMgr()->onScriptHitBreakpoint(script); + script->sleep(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 CBGame::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 CBGame::SaveGame(int slot, const char *desc, bool quickSave) { + char filename[MAX_PATH_LENGTH + 1]; + getSaveSlotFilename(slot, filename); + + LOG(0, "Saving game '%s'...", filename); + + _gameRef->applyEvent("BeforeSave", true); + + bool ret; + + _indicatorDisplay = true; + _indicatorProgress = 0; + CBPersistMgr *pm = new CBPersistMgr(_gameRef); + if (DID_FAIL(ret = pm->initSave(desc))) goto save_finish; + + if (!quickSave) { + delete _saveLoadImage; + _saveLoadImage = NULL; + if (_saveImageName) { + _saveLoadImage = _renderer->createSurface(); + + if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_saveImageName, true, 0, 0, 0))) { + delete _saveLoadImage; + _saveLoadImage = NULL; + } + } + } + + if (DID_FAIL(ret = CSysClassRegistry::getInstance()->saveTable(_gameRef, pm, quickSave))) goto save_finish; + if (DID_FAIL(ret = CSysClassRegistry::getInstance()->saveInstances(_gameRef, pm, quickSave))) goto save_finish; + if (DID_FAIL(ret = pm->saveFile(filename))) goto save_finish; + + _registry->writeInt("System", "MostRecentSaveSlot", slot); + +save_finish: // TODO: Remove gotos + delete pm; + _indicatorDisplay = false; + + delete _saveLoadImage; + _saveLoadImage = NULL; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::loadGame(int slot) { + //_gameRef->LOG(0, "Load start %d", CBUtils::GetUsedMemMB()); + + _loading = false; + _scheduledLoadSlot = -1; + + char filename[MAX_PATH_LENGTH + 1]; + getSaveSlotFilename(slot, filename); + + return loadGame(filename); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::loadGame(const char *filename) { + LOG(0, "Loading game '%s'...", filename); + getDebugMgr()->onGameShutdown(); + + bool ret; + + delete _saveLoadImage; + _saveLoadImage = NULL; + if (_loadImageName) { + _saveLoadImage = _renderer->createSurface(); + + if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_loadImageName, true, 0, 0, 0))) { + delete _saveLoadImage; + _saveLoadImage = NULL; + } + } + + + _loadInProgress = true; + _indicatorDisplay = true; + _indicatorProgress = 0; + CBPersistMgr *pm = new CBPersistMgr(_gameRef); + _debugAbsolutePathWarning = false; + if (DID_FAIL(ret = pm->initLoad(filename))) goto load_finish; + + //if(DID_FAIL(ret = cleanup())) goto load_finish; + if (DID_FAIL(ret = CSysClassRegistry::getInstance()->loadTable(_gameRef, pm))) goto load_finish; + if (DID_FAIL(ret = CSysClassRegistry::getInstance()->loadInstances(_gameRef, pm))) goto load_finish; + + // data initialization after load + initAfterLoad(); + + _gameRef->applyEvent("AfterLoad", true); + + displayContent(true, false); + //_renderer->flip(); + + getDebugMgr()->onGameInit(); + +load_finish: + _debugAbsolutePathWarning = true; + + _indicatorDisplay = false; + delete pm; + _loadInProgress = false; + + delete _saveLoadImage; + _saveLoadImage = NULL; + + //_gameRef->LOG(0, "Load end %d", CBUtils::GetUsedMemMB()); + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::initAfterLoad() { + CSysClassRegistry::getInstance()->enumInstances(afterLoadRegion, "CBRegion", NULL); + CSysClassRegistry::getInstance()->enumInstances(afterLoadSubFrame, "CBSubFrame", NULL); + CSysClassRegistry::getInstance()->enumInstances(afterLoadSound, "CBSound", NULL); + CSysClassRegistry::getInstance()->enumInstances(afterLoadFont, "CBFontTT", NULL); + CSysClassRegistry::getInstance()->enumInstances(afterLoadScript, "CScScript", NULL); + + _scEngine->refreshScriptBreakpoints(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::afterLoadRegion(void *region, void *data) { + ((CBRegion *)region)->createRegion(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::afterLoadSubFrame(void *subframe, void *data) { + ((CBSubFrame *)subframe)->setSurfaceSimple(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::afterLoadSound(void *sound, void *data) { + ((CBSound *)sound)->setSoundSimple(); +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::afterLoadFont(void *font, void *data) { + ((CBFont *)font)->afterLoad(); +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::afterLoadScript(void *script, void *data) { + ((CScScript *)script)->afterLoad(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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.getSize() - 1; i >= 0; i--) { + if (_windows[i]->_visible && !_windows[i]->_disable) { + _focusedWindow = _windows[i]; + break; + } + } + } + + // display all windows + for (int i = 0; i < _windows.getSize(); i++) { + if (_windows[i]->_visible && _windows[i]->_inGame == inGame) { + + res = _windows[i]->display(); + if (DID_FAIL(res)) return res; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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 CBSound(_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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 = _gameRef->_fileManager->readWholeFile(filename); + if (origBuffer == NULL) { + _gameRef->LOG(0, "CBGame::LoadSettings failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret = STATUS_OK; + + byte *buffer = origBuffer; + byte *params; + int cmd; + CBParser parser(_gameRef); + + 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: + _registry->setBasePath((char *)params); + break; + + case TOKEN_RICH_SAVED_GAMES: + parser.scanStr((char *)params, "%b", &_richSavedGames); + break; + + case TOKEN_SAVED_GAME_EXT: + CBUtils::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 = _registry->readBool("Debug", "AllowWindowed", _settingsAllowWindowed); + _compressedSavegames = _registry->readBool("Debug", "CompressedSavegames", _compressedSavegames); + //_compressedSavegames = false; + + delete [] origBuffer; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::persist(CBPersistMgr *persistMgr) { + if (!persistMgr->_saving) + cleanup(); + + CBObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_activeObject)); + persistMgr->transfer(TMEMBER(_capturedObject)); + persistMgr->transfer(TMEMBER(_cursorNoninteractive)); + persistMgr->transfer(TMEMBER(_doNotExpandStrings)); + 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)); + + persistMgr->transfer(TMEMBER(_loadImageName)); + persistMgr->transfer(TMEMBER(_saveImageName)); + persistMgr->transfer(TMEMBER(_saveImageX)); + persistMgr->transfer(TMEMBER(_saveImageY)); + persistMgr->transfer(TMEMBER(_loadImageX)); + persistMgr->transfer(TMEMBER(_loadImageY)); + + 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->_saving) + _quitting = false; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::focusWindow(CUIWindow *Window) { + CUIWindow *Prev = _focusedWindow; + + for (int i = 0; i < _windows.getSize(); i++) { + if (_windows[i] == Window) { + if (i < _windows.getSize() - 1) { + _windows.removeAt(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 CBGame::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 CBGame::unfreeze() { + if (_freezeLevel == 0) return STATUS_OK; + + _freezeLevel--; + if (_freezeLevel == 0) { + _state = _origState; + _interactive = _origInteractive; + _scEngine->resumeAll(); + _soundMgr->resumeAll(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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; + } + + if (event->type == Common::EVENT_KEYDOWN && event->kbd.keycode == Common::KEYCODE_RETURN && (event->kbd.flags == Common::KBD_ALT)) { + // TODO: Handle alt-enter as well as alt-return. + _renderer->switchFullscreen(); + 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; + } //else return true; + + return false; +} + +void CBGame::handleKeyRelease(Common::Event *event) { + _keyboardState->handleKeyRelease(event); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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 CBGame::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 CBGame::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("CBGame::SetWindowTitle -Ignoring textencoding"); + utf8Title = Utf8String(title); + /* WideString wstr = StringUtil::AnsiToWide(Title); + title = StringUtil::WideToUtf8(wstr);*/ + } +#if 0 + CBRenderOSystem *renderer = static_cast(_renderer); + // TODO + + SDL_SetWindowTitle(renderer->GetSdlWindow(), title.c_str()); +#endif + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::getSaveSlotFilename(int slot, char *buffer) { + AnsiString dataDir = getDataDir(); + //sprintf(Buffer, "%s/save%03d.%s", dataDir.c_str(), Slot, _savedGameExt); + CBPersistMgr *pm = new CBPersistMgr(_gameRef); + Common::String filename = pm->getFilenameForSlot(slot); + delete pm; + strcpy(buffer, filename.c_str()); + debugC(kWinterMuteDebugSaveGame, "getSaveSlotFileName(%d) = %s", slot, buffer); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString CBGame::getDataDir() { + AnsiString userDir = PathUtil::getUserDirectory(); + AnsiString baseDir = _registry->getBasePath(); + return PathUtil::combine(userDir, baseDir); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::getSaveSlotDescription(int slot, char *buffer) { + buffer[0] = '\0'; + + char filename[MAX_PATH_LENGTH + 1]; + getSaveSlotFilename(slot, filename); + CBPersistMgr *pm = new CBPersistMgr(_gameRef); + if (!pm) return STATUS_FAILED; + + _debugAbsolutePathWarning = false; + if (DID_FAIL(pm->initLoad(filename))) { + _debugAbsolutePathWarning = true; + delete pm; + return STATUS_FAILED; + } + + _debugAbsolutePathWarning = true; + strcpy(buffer, pm->_savedDescription); + delete pm; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::isSaveSlotUsed(int slot) { + char filename[MAX_PATH_LENGTH + 1]; + getSaveSlotFilename(slot, filename); + + warning("CBGame::IsSaveSlotUsed(%d) - FIXME, ugly solution", slot); + Common::SeekableReadStream *File = g_wintermute->getSaveFileMan()->openForLoading(filename); + if (!File) return false; + delete File; + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::emptySaveSlot(int slot) { + char filename[MAX_PATH_LENGTH + 1]; + getSaveSlotFilename(slot, filename); + CBPersistMgr *pm = new CBPersistMgr(this); + g_wintermute->getSaveFileMan()->removeSavefile(pm->getFilenameForSlot(slot)); + delete pm; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::setActiveObject(CBObject *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 CBGame::pushViewport(CBViewport *viewport) { + _viewportSP++; + if (_viewportSP >= _viewportStack.getSize()) _viewportStack.add(viewport); + else _viewportStack[_viewportSP] = viewport; + + _renderer->setViewport(viewport->getRect()); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::popViewport() { + _viewportSP--; + if (_viewportSP < -1) _gameRef->LOG(0, "Fatal: Viewport stack underflow!"); + + if (_viewportSP >= 0 && _viewportSP < _viewportStack.getSize()) _renderer->setViewport(_viewportStack[_viewportSP]->getRect()); + else _renderer->setViewport(_renderer->_drawOffsetX, + _renderer->_drawOffsetY, + _renderer->_width + _renderer->_drawOffsetX, + _renderer->_height + _renderer->_drawOffsetY); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::getCurrentViewportRect(Rect32 *rect, bool *custom) { + if (rect == NULL) return STATUS_FAILED; + else { + if (_viewportSP >= 0) { + CBPlatform::copyRect(rect, _viewportStack[_viewportSP]->getRect()); + if (custom) *custom = true; + } else { + CBPlatform::setRect(rect, _renderer->_drawOffsetX, + _renderer->_drawOffsetY, + _renderer->_width + _renderer->_drawOffsetX, + _renderer->_height + _renderer->_drawOffsetY); + if (custom) *custom = false; + } + + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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 CBGame::windowLoadHook(CUIWindow *win, char **buf, char **params) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::setInteractive(bool state) { + _interactive = state; + if (_transMgr) _transMgr->_origInteractive = state; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::resetMousePos() { + Common::Point p; + p.x = _mousePos.x + _renderer->_drawOffsetX; + p.y = _mousePos.y + _renderer->_drawOffsetY; + + CBPlatform::setCursorPos(p.x, p.y); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::displayContent(bool doUpdate, bool displayAll) { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::displayContentSimple() { + // fill black + _renderer->fill(0, 0, 0); + if (_indicatorDisplay) displayIndicator(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::displayIndicator() { + if (_saveLoadImage) { + Rect32 rc; + CBPlatform::setRect(&rc, 0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight()); + if (_loadInProgress) _saveLoadImage->displayTrans(_loadImageX, _loadImageY, rc); + else _saveLoadImage->displayTrans(_saveImageX, _saveImageY, rc); + } + + if ((!_indicatorDisplay && _indicatorWidth <= 0) || _indicatorHeight <= 0) return STATUS_OK; + _renderer->setupLines(); + for (int i = 0; i < _indicatorHeight; i++) + _renderer->drawLine(_indicatorX, _indicatorY + i, _indicatorX + (int)(_indicatorWidth * (float)((float)_indicatorProgress / 100.0f)), _indicatorY + i, _indicatorColor); + + _renderer->setup2D(); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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 + CBSound *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 CBGame::resetContent() { + _scEngine->clearGlobals(); + //_timer = 0; + //_liveTimer = 0; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::DEBUG_DumpClassRegistry() { + warning("DEBUG_DumpClassRegistry - untested"); + Common::DumpFile *f = new Common::DumpFile; + f->open("zz_class_reg_dump.log"); + + CSysClassRegistry::getInstance()->dumpClasses(f); + + f->close(); + delete f; + _gameRef->quickMessage("Classes dump completed."); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::invalidateDeviceObjects() { + for (int i = 0; i < _regObjects.getSize(); i++) { + _regObjects[i]->invalidateDeviceObjects(); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::restoreDeviceObjects() { + for (int i = 0; i < _regObjects.getSize(); i++) { + _regObjects[i]->restoreDeviceObjects(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::setWaitCursor(const char *filename) { + delete _cursorNoninteractive; + _cursorNoninteractive = NULL; + + _cursorNoninteractive = new CBSprite(_gameRef); + if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile(filename))) { + delete _cursorNoninteractive; + _cursorNoninteractive = NULL; + return STATUS_FAILED; + } else return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::isVideoPlaying() { + if (_videoPlayer->isPlaying()) return true; + if (_theoraPlayer && _theoraPlayer->isPlaying()) return true; + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::stopVideo() { + if (_videoPlayer->isPlaying()) _videoPlayer->stop(); + if (_theoraPlayer && _theoraPlayer->isPlaying()) { + _theoraPlayer->stop(); + delete _theoraPlayer; + _theoraPlayer = NULL; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::drawCursor(CBSprite *cursor) { + if (!cursor) return STATUS_FAILED; + if (cursor != _lastCursor) { + cursor->reset(); + _lastCursor = cursor; + } + return cursor->draw(_mousePos.x, _mousePos.y); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CBGame::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 CBGame::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; + CBPlatform::setCapture(/*_renderer->_window*/); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::onMouseLeftUp() { + if (_activeObject) _activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT); + + CBPlatform::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::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 CBGame::onPaint() { + if (_renderer && _renderer->_windowed && _renderer->_ready) { + _renderer->initLoop(); + displayContent(false, true); + displayDebugInfo(); + _renderer->windowedBlt(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::onWindowClose() { + if (canHandleEvent("QuitGame")) { + if (_state != GAME_FROZEN) _gameRef->applyEvent("QuitGame"); + return STATUS_OK; + } else return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::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()); + 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((byte *)_activeObject->_name, 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; +} + +////////////////////////////////////////////////////////////////////////// +CBDebugger *CBGame::getDebugMgr() { + if (!_debugMgr) _debugMgr = new CBDebugger(this); + return _debugMgr; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::getMousePos(Point32 *pos) { + CBPlatform::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 (!CBPlatform::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; + + CBPlatform::setCursorPos(newPos.x, newPos.y); + } + } +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::miniUpdate() { + if (!_miniUpdateEnabled) return STATUS_OK; + + if (CBPlatform::getTime() - _lastMiniUpdate > 200) { + if (_soundMgr) _soundMgr->initLoop(); + _lastMiniUpdate = CBPlatform::getTime(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::onScriptShutdown(CScScript *script) { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::isLeftDoubleClick() { + return isDoubleClick(0); +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::isRightDoubleClick() { + return isDoubleClick(1); +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::isDoubleClick(int buttonIndex) { + uint32 maxDoubleCLickTime = 500; + int maxMoveX = 4; + int maxMoveY = 4; + + Point32 pos; + CBPlatform::getCursorPos(&pos); + + int moveX = abs(pos.x - _lastClick[buttonIndex].posX); + int moveY = abs(pos.y - _lastClick[buttonIndex].posY); + + + if (_lastClick[buttonIndex].time == 0 || CBPlatform::getTime() - _lastClick[buttonIndex].time > maxDoubleCLickTime || moveX > maxMoveX || moveY > maxMoveY) { + _lastClick[buttonIndex].time = CBPlatform::getTime(); + _lastClick[buttonIndex].posX = pos.x; + _lastClick[buttonIndex].posY = pos.y; + return false; + } else { + _lastClick[buttonIndex].time = 0; + return true; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::autoSaveOnExit() { + _soundMgr->saveSettings(); + _registry->saveValues(); + + if (!_autoSaveOnExit) return; + if (_state == GAME_FROZEN) return; + + SaveGame(_autoSaveSlot, "autosave", true); +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::addMem(int bytes) { + _usedMem += bytes; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString CBGame::getDeviceType() const { + return "computer"; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h new file mode 100644 index 0000000000..12ab07912b --- /dev/null +++ b/engines/wintermute/base/base_game.h @@ -0,0 +1,391 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BGAME_H +#define WINTERMUTE_BGAME_H + +#include "engines/wintermute/base/base_Debugger.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 CBSoundMgr; +class CBFader; +class CBFont; +class CBFileManager; +class CBTransitionMgr; +class CScEngine; +class CBFontStorage; +class CBStringTable; +class CBQuickMsg; +class CUIWindow; +class CBViewport; +class CBRenderer; +class CBRegistry; +class CBSaveThumbHelper; +class CBSurfaceStorage; +class CSXMath; +class CBKeyboardState; +class CVidPlayer; +class CVidTheoraPlayer; + +#define NUM_MUSIC_CHANNELS 5 + +class CBGame: public CBObject { +public: + DECLARE_PERSISTENT(CBGame, CBObject) + + virtual bool onScriptShutdown(CScScript *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 bool miniUpdate(); + + void getMousePos(Point32 *Pos); + Rect32 _mouseLockRect; + + bool _shuttingDown; + + virtual bool displayDebugInfo(); + bool _debugShowFPS; + + bool _suspendedRendering; + int _soundBufferSizeSec; + + TTextEncoding _textEncoding; + bool _textRTL; + + CBSprite *_loadingIcon; + int _loadingIconX; + int _loadingIconY; + int _loadingIconPersistent; + + virtual bool resetContent(); + + void DEBUG_DumpClassRegistry(); + bool setWaitCursor(const char *filename); + char *_localSaveDir; + bool _saveDirChecked; + + int _indicatorProgress; +protected: + bool _indicatorDisplay; + uint32 _indicatorColor; + int _indicatorX; + int _indicatorY; + int _indicatorWidth; + int _indicatorHeight; + + bool _richSavedGames; + char *_savedGameExt; + + char *_loadImageName; + char *_saveImageName; + int _saveImageX; + int _saveImageY; + int _loadImageX; + int _loadImageY; + + CBSurface *_saveLoadImage; + bool displayIndicator(); + + bool _reportTextureFormat; +public: + int _thumbnailWidth; + int _thumbnailHeight; + + void setEngineLogCallback(ENGINE_LOG_CALLBACK callback = NULL, void *data = NULL); + ENGINE_LOG_CALLBACK _engineLogCallback; + void *_engineLogCallbackData; + bool _editorMode; + + bool _doNotExpandStrings; + void getOffset(int *offsetX, int *offsetY); + void setOffset(int offsetX, int offsetY); + int getSequence(); + int _offsetY; + int _offsetX; + float _offsetPercentX; + float _offsetPercentY; + CBObject *_mainObject; + + bool initInput(); + bool initLoop(); + uint32 _currentTime; + uint32 _deltaTime; + CBFont *_systemFont; + CBFont *_videoFont; + bool initialize1(); + bool initialize2(); + bool initialize3(); + CBFileManager *_fileManager; + CBTransitionMgr *_transMgr; + CBDebugger *getDebugMgr(); + + void LOG(bool res, const char *fmt, ...); + + CBRenderer *_renderer; + CBSoundMgr *_soundMgr; + CScEngine *_scEngine; + CSXMath *_mathClass; + CBSurfaceStorage *_surfaceStorage; + CBFontStorage *_fontStorage; + CBGame(); + + virtual ~CBGame(); + void DEBUG_DebugDisable(); + void DEBUG_DebugEnable(const char *filename = NULL); + bool _debugDebugMode; + bool _debugAbsolutePathWarning; + + void *_debugLogFile; + int _sequence; + virtual bool loadFile(const char *filename); + virtual bool loadBuffer(byte *buffer, bool complete = true); + CBArray _quickMessages; + CBArray _windows; + CBArray _viewportStack; + + int _viewportSP; + + CBStringTable *_stringTable; + int _settingsResWidth; + int _settingsResHeight; + char *_settingsGameFile; + bool _suppressScriptErrors; + bool _mouseLeftDown; +protected: + bool _mouseRightDown; + bool _mouseMidlleDown; + bool _settingsRequireAcceleration; + bool _settingsAllowWindowed; + bool _settingsAllowAdvanced; + bool _settingsAllowAccessTab; + bool _settingsAllowAboutTab; + bool _settingsRequireSound; + bool _settingsAllowDesktopRes; + int _settingsTLMode; + CBFader *_fader; + virtual bool invalidateDeviceObjects(); + virtual bool restoreDeviceObjects(); +public: + virtual bool ExternalCall(CScScript *script, CScStack *stack, CScStack *thisStack, char *name); + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + // compatibility bits + bool _compatKillMethodThreads; + +private: + // FPS stuff + uint32 _lastTime; + uint32 _fpsTime; + uint32 _framesRendered; + Common::String _gameId; +public: + const char* getGameId() { return _gameId.c_str(); } + void setGameId(const Common::String& gameId) { _gameId = gameId; } + uint32 _surfaceGCCycleTime; + bool _smartCache; + bool _videoSubtitles; + bool _subtitles; + uint32 _musicStartTime[NUM_MUSIC_CHANNELS]; + bool _compressedSavegames; + int _scheduledLoadSlot; + bool _loading; + bool _personalizedSave; + bool emptySaveSlot(int slot); + bool isSaveSlotUsed(int slot); + bool getSaveSlotDescription(int slot, char *buffer); + bool getSaveSlotFilename(int slot, char *buffer); + void setWindowTitle(); + 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); +protected: + int _freezeLevel; +public: + bool unfreeze(); + bool freeze(bool includingMusic = true); + bool focusWindow(CUIWindow *window); + CVidPlayer *_videoPlayer; + CVidTheoraPlayer *_theoraPlayer; + bool _loadInProgress; + CUIWindow *_focusedWindow; + bool _editorForceScripts; +protected: + static void afterLoadRegion(void *region, void *data); + static void afterLoadSubFrame(void *subframe, void *data); + static void afterLoadSound(void *sound, void *data); + static void afterLoadFont(void *font, void *data); + static void afterLoadScript(void *script, void *data); +public: + static void invalidateValues(void *value, void *data); + + bool loadSettings(const char *filename); + 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); + CBSound *_music[NUM_MUSIC_CHANNELS]; + bool _musicCrossfadeRunning; + bool _musicCrossfadeSwap; + uint32 _musicCrossfadeStartTime; + uint32 _musicCrossfadeLength; + int _musicCrossfadeChannel1; + int _musicCrossfadeChannel2; + bool displayWindows(bool inGame = false); + CBRegistry *_registry; + bool _useD3D; + virtual bool cleanup(); + virtual bool loadGame(int slot); + virtual bool loadGame(const char *filename); + virtual bool SaveGame(int slot, const char *desc, bool quickSave = false); + virtual bool showCursor(); + + CBSprite *_cursorNoninteractive; + CBObject *_activeObject; + CBKeyboardState *_keyboardState; + bool _interactive; + TGameState _state; + TGameState _origState; + bool _origInteractive; + uint32 _timer; + uint32 _timerDelta; + uint32 _timerLast; + + uint32 _liveTimer; + uint32 _liveTimerDelta; + uint32 _liveTimerLast; + + CBObject *_capturedObject; + Point32 _mousePos; + bool validObject(CBObject *object); + bool unregisterObject(CBObject *object); + bool registerObject(CBObject *object); + void quickMessage(const char *text); + void quickMessageForm(char *fmt, ...); + bool displayQuickMsg(); + uint32 _fps; + bool updateMusicCrossfade(); + + bool isVideoPlaying(); + bool stopVideo(); + + CBArray _regObjects; +public: + 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(CUIWindow *win, char **buf, char **params); + virtual bool windowScriptMethodHook(CUIWindow *win, CScScript *script, CScStack *stack, const char *name); + bool getCurrentViewportOffset(int *offsetX = NULL, int *offsetY = NULL); + bool getCurrentViewportRect(Rect32 *rect, bool *custom = NULL); + bool popViewport(); + bool pushViewport(CBViewport *Viewport); + bool setActiveObject(CBObject *Obj); + CBSprite *_lastCursor; + bool drawCursor(CBSprite *Cursor); + + virtual bool initAfterLoad(); + CBSaveThumbHelper *_cachedThumbnail; + AnsiString getDataDir(); + void addMem(int bytes); + + bool _touchInterface; + bool _constrainedMemory; + AnsiString getDeviceType() const; + +private: + CBDebugger *_debugMgr; + + struct LastClickInfo { + LastClickInfo() { + posX = posY = 0; + time = 0; + } + + int posX; + int posY; + uint32 time; + }; + + LastClickInfo _lastClick[2]; + bool isDoubleClick(int buttonIndex); + uint32 _usedMem; + + + +protected: + // WME Lite specific + bool _autoSaveOnExit; + int _autoSaveSlot; + bool _cursorHidden; + +public: + void autoSaveOnExit(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp new file mode 100644 index 0000000000..240f642b7f --- /dev/null +++ b/engines/wintermute/base/base_keyboard_state.cpp @@ -0,0 +1,304 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CBKeyboardState, false) + +////////////////////////////////////////////////////////////////////////// +CBKeyboardState::CBKeyboardState(CBGame *inGame): CBScriptable(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; + } +} + +////////////////////////////////////////////////////////////////////////// +CBKeyboardState::~CBKeyboardState() { + delete[] _keyStates; +} + +void CBKeyboardState::handleKeyPress(Common::Event *event) { + if (event->type == Common::EVENT_KEYDOWN) { + _keyStates[event->kbd.keycode] = true; + } +} + +void CBKeyboardState::handleKeyRelease(Common::Event *event) { + if (event->type == Common::EVENT_KEYUP) { + _keyStates[event->kbd.keycode] = false; + } +} + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // IsKeyDown + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "IsKeyDown") == 0) { + stack->correctParams(1); + CScValue *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(); + + warning("BKeyboardState doesnt yet have state-support %d", vKey); //TODO; +// Uint8 *state = SDL_GetKeyboardState(NULL); +// SDL_Scancode scanCode = SDL_GetScancodeFromKey(VKeyToKeyCode(vKey)); + bool isDown = _keyStates[vKeyToKeyCode(vKey)]; + + stack->pushBool(isDown); + return STATUS_OK; + } + + else return CBScriptable::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBKeyboardState::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 CBScriptable::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::scSetProperty(const char *name, CScValue *value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + if (_renderer) SetWindowText(_renderer->_window, _name); + return STATUS_OK; + } + + else*/ return CBScriptable::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBKeyboardState::scToString() { + return "[keyboard state]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::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)) { + _currentPrintable = true; + } else { + _currentPrintable = false; + } + //_currentKeyData = KeyData; + + _currentControl = isControlDown(); + _currentAlt = isAltDown(); + _currentShift = isShiftDown(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::persist(CBPersistMgr *persistMgr) { + //if(!persistMgr->_saving) cleanup(); + CBScriptable::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->_saving) { + _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 CBKeyboardState::isShiftDown() { + int mod = g_system->getEventManager()->getModifierState(); + return (mod & Common::KBD_SHIFT); +} + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::isControlDown() { + int mod = g_system->getEventManager()->getModifierState(); + return (mod & Common::KBD_CTRL); +} + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::isAltDown() { + int mod = g_system->getEventManager()->getModifierState(); + return (mod & Common::KBD_ALT); +} + +////////////////////////////////////////////////////////////////////////// +uint32 CBKeyboardState::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 { + VK_SPACE = 32, + VK_LEFT = 37, + VK_UP = 38, + VK_RIGHT = 39, + VK_DOWN = 40 +}; + +////////////////////////////////////////////////////////////////////////// +Common::KeyCode CBKeyboardState::vKeyToKeyCode(uint32 vkey) { + // todo + switch (vkey) { + case VK_SPACE: + return Common::KEYCODE_SPACE; + break; + case VK_LEFT: + return Common::KEYCODE_LEFT; + break; + case VK_RIGHT: + return Common::KEYCODE_RIGHT; + break; + case VK_UP: + return Common::KEYCODE_UP; + break; + case VK_DOWN: + return Common::KEYCODE_DOWN; + break; + default: + warning("Unknown VKEY: %d", vkey); + return (Common::KeyCode)vkey; + break; + } + +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h new file mode 100644 index 0000000000..bdf268c601 --- /dev/null +++ b/engines/wintermute/base/base_keyboard_state.h @@ -0,0 +1,75 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BKEYBOARD_STATE_H +#define WINTERMUTE_BKEYBOARD_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 CBKeyboardState : public CBScriptable { +public: + uint32 _currentKeyData; + uint32 _currentCharCode; + bool _currentPrintable; + + bool _currentShift; + bool _currentAlt; + bool _currentControl; + + DECLARE_PERSISTENT(CBKeyboardState, CBScriptable) + CBKeyboardState(CBGame *inGame); + virtual ~CBKeyboardState(); + 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 CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + +private: + uint8 *_keyStates; + uint32 keyCodeToVKey(Common::Event *event); + Common::KeyCode vKeyToKeyCode(uint32 vkey); //TODO, reimplement using ScummVM-backend +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_named_object.cpp b/engines/wintermute/base/base_named_object.cpp new file mode 100644 index 0000000000..da76fb2047 --- /dev/null +++ b/engines/wintermute/base/base_named_object.cpp @@ -0,0 +1,65 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/base_named_object.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBNamedObject::CBNamedObject(CBGame *inGame) : CBBase(inGame) { + _name = NULL; +} + +////////////////////////////////////////////////////////////////////////// +CBNamedObject::CBNamedObject() : CBBase() { + _name = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBNamedObject::CBNamedObject(TDynamicConstructor, TDynamicConstructor) { + _name = NULL; +} + +////////////////////////////////////////////////////////////////////////// +CBNamedObject::~CBNamedObject(void) { + delete[] _name; + _name = NULL; +} + + +////////////////////////////////////////////////////////////////////// +void CBNamedObject::setName(const char *name) { + delete[] _name; + + _name = new char [strlen(name) + 1]; + if (_name != NULL) strcpy(_name, name); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_named_object.h b/engines/wintermute/base/base_named_object.h new file mode 100644 index 0000000000..c03d1417a3 --- /dev/null +++ b/engines/wintermute/base/base_named_object.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BNAMEDOBJECT_H +#define WINTERMUTE_BNAMEDOBJECT_H + + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBNamedObject : public CBBase { +public: + CBNamedObject(CBGame *inGame); + CBNamedObject(); + virtual ~CBNamedObject(void); + CBNamedObject(TDynamicConstructor, TDynamicConstructor); + + char *_name; + void setName(const char *name); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp new file mode 100644 index 0000000000..0a4a0638f0 --- /dev/null +++ b/engines/wintermute/base/base_object.cpp @@ -0,0 +1,1128 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CBObject, false) + +////////////////////////////////////////////////////////////////////// +CBObject::CBObject(CBGame *inGame): CBScriptHolder(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(); + + CBPlatform::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; +} + + +////////////////////////////////////////////////////////////////////// +CBObject::~CBObject() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::cleanup() { + if (_gameRef && _gameRef->_activeObject == this) + _gameRef->_activeObject = NULL; + + CBScriptHolder::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 CBObject::setCaption(const char *caption, int caseVal) { // TODO: rename Case to something usefull + 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 *CBObject::getCaption(int caseVal) { + if (caseVal == 0) caseVal = 1; + if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == NULL) + return ""; + else return _caption[caseVal - 1]; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::listen(CBScriptHolder *param1, uint32 param2) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CBObject::scCallMethod(CScScript *script, CScStack *stack, CScStack *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->_filename) stack->pushNULL(); + else stack->pushString(_cursor->_filename); + + 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; + + CScValue *val1 = stack->pop(); + CScValue *val2 = stack->pop(); + CScValue *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; + + CScValue *val1 = stack->pop(); + CScValue *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 CBScriptHolder::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBObject::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 CBScriptHolder::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::scSetProperty(const char *name, CScValue *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 CBScriptHolder::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBObject::scToString() { + return "[object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::showCursor() { + if (_cursor) return _gameRef->drawCursor(_cursor); + else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::saveAsText(CBDynBuffer *buffer, int indent) { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::persist(CBPersistMgr *persistMgr) { + CBScriptHolder::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 CBObject::setCursor(const char *filename) { + if (!_sharedCursors) { + delete _cursor; + _cursor = NULL; + } + + _sharedCursors = false; + _cursor = new CBSprite(_gameRef); + if (!_cursor || DID_FAIL(_cursor->loadFile(filename))) { + delete _cursor; + _cursor = NULL; + return STATUS_FAILED; + } else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::setActiveCursor(const char *filename) { + delete _activeCursor; + _activeCursor = new CBSprite(_gameRef); + if (!_activeCursor || DID_FAIL(_activeCursor->loadFile(filename))) { + delete _activeCursor; + _activeCursor = NULL; + return STATUS_FAILED; + } else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBObject::getHeight() { + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::handleMouse(TMouseEvent event, TMouseButton button) { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::handleKeypress(Common::Event *event, bool printable) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::handleMouseWheel(int delta) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::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 CBSound(_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 CBObject::stopSFX(bool deleteSound) { + if (_sFX) { + _sFX->stop(); + if (deleteSound) { + delete _sFX; + _sFX = NULL; + } + return STATUS_OK; + } else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::pauseSFX() { + if (_sFX) return _sFX->pause(); + else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::resumeSFX() { + if (_sFX) return _sFX->resume(); + else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::setSFXTime(uint32 time) { + _sFXStart = time; + if (_sFX && _sFX->isPlaying()) return _sFX->setPositionTime(time); + else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::setSFXVolume(int volume) { + _sFXVolume = volume; + if (_sFX) return _sFX->setVolumePercent(volume); + else return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::updateSounds() { + if (_soundEvent) { + if (_sFX && !_sFX->isPlaying()) { + applyEvent(_soundEvent); + setSoundEvent(NULL); + } + } + + if (_sFX) updateOneSound(_sFX); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBObject::updateOneSound(CBSound *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 CBObject::resetSoundPan() { + if (!_sFX) return STATUS_OK; + else { + return _sFX->setPan(0.0f); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::getExtendedFlag(const char *flagName) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBObject::isReady() { + return _ready; +} + + +////////////////////////////////////////////////////////////////////////// +void CBObject::setSoundEvent(const char *eventName) { + delete[] _soundEvent; + _soundEvent = NULL; + if (eventName) { + _soundEvent = new char[strlen(eventName) + 1]; + if (_soundEvent) strcpy(_soundEvent, eventName); + } +} + +////////////////////////////////////////////////////////////////////////// +bool CBObject::afterMove() { + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h new file mode 100644 index 0000000000..70dc69f53d --- /dev/null +++ b/engines/wintermute/base/base_object.h @@ -0,0 +1,144 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BOBJECT_H +#define WINTERMUTE_BOBJECT_H + + +#include "engines/wintermute/base/base_script_holder.h" +#include "engines/wintermute/persistent.h" +#include "common/events.h" + +namespace WinterMute { + +class CBSprite; +class CBSound; +class CBSurface; +class CBScriptHolder; +class CScValue; +class CScStack; +class CScScript; +class CBObject : public CBScriptHolder { +public: + TSpriteBlendMode _blendMode; + virtual bool afterMove(); + float _relativeRotate; + bool _rotateValid; + float _rotate; + void setSoundEvent(const char *eventName); + bool _rotatable; + uint32 _alphaColor; + float _scale; + float _scaleX; + float _scaleY; + float _relativeScale; + virtual bool isReady(); + virtual bool getExtendedFlag(const char *flagName); + virtual bool resetSoundPan(); + virtual bool updateSounds(); + bool updateOneSound(CBSound *sound); + bool _autoSoundPanning; + uint32 _sFXStart; + int _sFXVolume; + 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); + CBSound *_sFX; + + TSFXType _sFXType; + float _sFXParam1; + float _sFXParam2; + float _sFXParam3; + float _sFXParam4; + + 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 _editorSelected; + bool _editorAlwaysRegister; + bool _editorOnly; + bool _is3D; + DECLARE_PERSISTENT(CBObject, CBScriptHolder) + virtual bool showCursor(); + CBSprite *_cursor; + bool _sharedCursors; + CBSprite *_activeCursor; + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + virtual bool listen(CBScriptHolder *param1, uint32 param2); + bool _ready; + bool _registrable; + bool _zoomable; + bool _shadowable; + Rect32 _rect; + bool _rectSet; + int _iD; + bool _movable; + CBObject(CBGame *inGame); + virtual ~CBObject(); + char *_caption[7]; + char *_soundEvent; + int _posY; + int _posX; + bool _saveState; + + // 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 CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_parser.cpp b/engines/wintermute/base/base_parser.cpp new file mode 100644 index 0000000000..0f185636aa --- /dev/null +++ b/engines/wintermute/base/base_parser.cpp @@ -0,0 +1,436 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" +#include "common/util.h" + +#define WHITESPACE " \t\n\r" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////// +CBParser::CBParser(CBGame *inGame): CBBase(inGame) { + _whiteSpace = new char [strlen(WHITESPACE) + 1]; + strcpy(_whiteSpace, WHITESPACE); +} + + +////////////////////////////////////////////////////////////////////// +CBParser::~CBParser() { + if (_whiteSpace != NULL) delete [] _whiteSpace; +} + + +////////////////////////////////////////////////////////////////////// +char *CBParser::getLastOffender() { + return _lastOffender; +} + + +////////////////////////////////////////////////////////////////////// +int32 CBParser::getObject(char **buf, 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. + // 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 CBParser::getCommand(char **buf, TokenDesc *tokens, char **params) { + if (!*buf) return PARSERR_TOKENNOTFOUND; + _gameRef->miniUpdate(); + char *name; + return getObject(buf, tokens, &name, params); +} + + +////////////////////////////////////////////////////////////////////// +void CBParser::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 *CBParser::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 *CBParser::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; +} + + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +char *CBParser::getToken(char **buf) { + static char token[100]; + 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 CBParser::getTokenFloat(char **buf) { + char *t = getToken(buf); + 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 CBParser::getTokenInt(char **buf) { + char *t = getToken(buf); + if (!((*t >= '0' && *t <= '9') || *t == '-')) { + // Error situation. We handle this by return 0. + return 0; + } + int rc = atoi(t); + return rc; +} + + +////////////////////////////////////////////////////////////////////// +void CBParser::skipToken(char **buf, char *tok, char * /*msg*/) { + char *t = getToken(buf); + if (strcmp(t, tok)) return; // Error +} + + +////////////////////////////////////////////////////////////////////// +int CBParser::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) { + strncpy(a, in, (int)(in2 - in)); + a[(int)(in2 - in)] = 0; + in = in2 + 1; + } else { + strcpy(a, in); + in = strchr(in, 0); + } + } else { + const char *in2 = in + strspn(in, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789."); + strncpy(a, in, (int)(in2 - in)); + a[(int)(in2 - in)] = 0; + in = in2; + } + in += strspn(in, " \t\n\f"); + num++; + break; + } + case 'S': { + char *a = va_arg(arg, char *); + in += strspn(in, " \t\n\f"); + if (*in == '\"') { + in++; + while (*in != '\"') { + if (*in == '\\') { + in++; + switch (*in) { + case '\\': + *a++ = '\\'; + break; + case 'n': + *a++ = '\n'; + break; + case 'r': + *a++ = '\r'; + break; + case 't': + *a++ = '\t'; + break; + case '"': + *a++ = '"'; + break; + default: + *a++ = '\\'; + *a++ = *in; + break; + } //switch + in++; + } else { + *a++ = *in++; + } + } //while in string + in++; + num++; + } //if string started + + //terminate string + *a = '\0'; + break; + } + } + if (*format) format++; + } else if (*format == ' ') { + format++; + in += strspn(in, " \t\n\f"); + } else if (*in == *format) { + in++; + format++; + } else { + num = -1; + break; + } + } + + va_end(arg); + + return num; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_parser.h b/engines/wintermute/base/base_parser.h new file mode 100644 index 0000000000..53a02c0f68 --- /dev/null +++ b/engines/wintermute/base/base_parser.h @@ -0,0 +1,89 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPARSER_H +#define WINTERMUTE_BPARSER_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 CBParser::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/base/base.h" +#include "engines/wintermute/coll_templ.h" + +namespace WinterMute { + +class CBParser : public CBBase { +public: + struct TokenDesc { + int32 id; + const char *token; + }; + +public: + int scanStr(const char *in, const char *format, ...); + int32 getCommand(char **buf, TokenDesc *tokens, char **params); + CBParser(CBGame *inGame = NULL); + virtual ~CBParser(); +private: + char *getLastOffender(); + void skipToken(char **buf, char *tok, char *msg = NULL); + int getTokenInt(char **buf); + float getTokenFloat(char **buf); + char *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, TokenDesc *tokens, char **name, char **data); + int _parserLine; + char _lastOffender[255]; + char *_whiteSpace; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp new file mode 100644 index 0000000000..743eaf355b --- /dev/null +++ b/engines/wintermute/base/base_persistence_manager.cpp @@ -0,0 +1,778 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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/utils/string_util.h" +#include "engines/wintermute/base/gfx/base_image.h" +#include "engines/wintermute/base/sound/base_sound.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 + +////////////////////////////////////////////////////////////////////////// +CBPersistMgr::CBPersistMgr(CBGame *inGame, const char *savePrefix): CBBase(inGame) { + _saving = false; +// _buffer = NULL; +// _bufferSize = 0; + _offset = 0; + _saveStream = NULL; + _loadStream = 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"; + } +} + + +////////////////////////////////////////////////////////////////////////// +CBPersistMgr::~CBPersistMgr() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::getSaveStateDesc(int slot, SaveStateDescriptor &desc) { + Common::String filename = getFilenameForSlot(slot); + warning("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 CBPersistMgr::deleteSaveSlot(int slot) { + Common::String filename = getFilenameForSlot(slot); + g_system->getSavefileManager()->removeSavefile(filename); +} + +uint32 CBPersistMgr::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 CBPersistMgr::getSaveExists(int slot) { + Common::String filename = getFilenameForSlot(slot); + warning("Trying to list savegame %s in slot %d", filename.c_str(), slot); + if (DID_FAIL(readHeader(filename))) { + return false; + } + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool CBPersistMgr::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 CBSaveThumbHelper(_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->_name); + + // 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 CBPersistMgr::readHeader(const Common::String &filename) { + cleanup(); + + _saving = false; + + _loadStream = g_system->getSavefileManager()->openForLoading(filename); + //_buffer = _gameRef->_fileManager->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 CBPersistMgr::initLoad(const char *filename) { + if (DID_FAIL(readHeader(filename))) { + cleanup(); + return STATUS_FAILED; + } + _saving = false; + + if (_savedName == "" || scumm_stricmp(_savedName.c_str(), _gameRef->_name) != 0) { + _gameRef->LOG(0, "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) + ) { + _gameRef->LOG(0, "ERROR: Saved game version is newer than current game"); + _gameRef->LOG(0, "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) + ) { + _gameRef->LOG(0, "ERROR: Saved game is too old and cannot be used by this version of game engine"); + _gameRef->LOG(0, "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 ( _savedVerMajor != DCGF_VER_MAJOR || _savedVerMinor != DCGF_VER_MINOR) + { + _gameRef->LOG(0, "ERROR: Saved game is created by other WME version"); + goto init_fail; + } + */ + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBPersistMgr::saveFile(const char *filename) { + return _gameRef->_fileManager->saveFile(filename, ((Common::MemoryWriteStreamDynamic *)_saveStream)->getData(), ((Common::MemoryWriteStreamDynamic *)_saveStream)->size(), _gameRef->_compressedSavegames, _richBuffer, _richBufferSize); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBPersistMgr::putBytes(byte *buffer, uint32 size) { + _saveStream->write(buffer, size); + if (_saveStream->err()) + return STATUS_FAILED; + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBPersistMgr::getBytes(byte *buffer, uint32 size) { + _loadStream->read(buffer, size); + if (_loadStream->err()) + return STATUS_FAILED; + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBPersistMgr::putDWORD(uint32 val) { + _saveStream->writeUint32LE(val); +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBPersistMgr::getDWORD() { + uint32 ret = _loadStream->readUint32LE(); + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +void CBPersistMgr::putString(const Common::String &val) { + if (!val.size()) putString("(null)"); + else { + _saveStream->writeUint32LE(val.size()); + _saveStream->writeString(val); + } +} + +Common::String CBPersistMgr::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 *CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::putFloat(float val) { + Common::String str = Common::String::format("F%f", val); + _saveStream->writeUint32LE(str.size()); + _saveStream->writeString(str); +} + +float CBPersistMgr::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 CBPersistMgr::putDouble(double val) { + Common::String str = Common::String::format("F%f", val); + str.format("D%f", val); + _saveStream->writeUint32LE(str.size()); + _saveStream->writeString(str); +} + +double CBPersistMgr::getDouble() { + char *str = getString(); + double value = 0.0f; + int ret = sscanf(str, "F%f", &value); + if (ret != 1) { + warning("%s not parsed as float", str); + } + delete[] str; + return value; +} + +////////////////////////////////////////////////////////////////////////// +// bool +bool CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::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 CBPersistMgr::transfer(const char *name, void *val) { + int classID = -1, instanceID = -1; + + if (_saving) { + CSysClassRegistry::getInstance()->getPointerID(*(void **)val, &classID, &instanceID); + if (*(void **)val != NULL && (classID == -1 || instanceID == -1)) { + _gameRef->LOG(0, "Warning: invalid instance '%s'", name); + } + + _saveStream->writeUint32LE(classID); + _saveStream->writeUint32LE(instanceID); + } else { + classID = _loadStream->readUint32LE(); + instanceID = _loadStream->readUint32LE(); + + *(void **)val = CSysClassRegistry::getInstance()->idToPointer(classID, instanceID); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBPersistMgr::checkVersion(byte verMajor, byte verMinor, byte verBuild) { + if (_saving) return true; + + // it's ok if we are same or newer than the saved game + if (verMajor > _savedVerMajor || + (verMajor == _savedVerMajor && verMinor > _savedVerMinor) || + (verMajor == _savedVerMajor && verMinor == _savedVerMinor && verBuild > _savedVerBuild) + ) return false; + + return true; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h new file mode 100644 index 0000000000..f2fd42ceca --- /dev/null +++ b/engines/wintermute/base/base_persistence_manager.h @@ -0,0 +1,114 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPERSISTMGR_H +#define WINTERMUTE_BPERSISTMGR_H + + +#include "engines/wintermute/base/base.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 CBPersistMgr : public CBBase { +public: + char *_savedDescription; + TimeDate _savedTimestamp; + uint32 _savedPlayTime; + byte _savedVerMajor; + byte _savedVerMinor; + byte _savedVerBuild; + byte _savedExtMajor; + byte _savedExtMinor; + Common::String _savePrefix; + Common::String _savedName; + bool saveFile(const char *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 char *filename); + bool initSave(const char *desc); + bool getBytes(byte *buffer, uint32 size); + bool putBytes(byte *buffer, uint32 size); + uint32 _offset; + + bool _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); + CBPersistMgr(CBGame *inGame = NULL, const char *savePrefix = NULL); + virtual ~CBPersistMgr(); + bool checkVersion(byte verMajor, byte verMinor, byte verBuild); + + uint32 _thumbnailDataSize; + byte *_thumbnailData; + Common::String getFilenameForSlot(int slot) const; +private: + bool readHeader(const Common::String &filename); + TimeDate getTimeDate(); + bool putTimeDate(const TimeDate &t); + Common::WriteStream *_saveStream; + Common::SeekableReadStream *_loadStream; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_point.cpp b/engines/wintermute/base/base_point.cpp new file mode 100644 index 0000000000..6887349a7a --- /dev/null +++ b/engines/wintermute/base/base_point.cpp @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * 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_Point.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBPoint, false) + +////////////////////////////////////////////////////////////////////////// +CBPoint::CBPoint() { + x = y = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBPoint::~CBPoint() { + +} + + +////////////////////////////////////////////////////////////////////////// +CBPoint::CBPoint(int initX, int initY) { + x = initX; + y = initY; +} + +////////////////////////////////////////////////////////////////////////// +bool CBPoint::persist(CBPersistMgr *persistMgr) { + + persistMgr->transfer(TMEMBER(x)); + persistMgr->transfer(TMEMBER(y)); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_point.h b/engines/wintermute/base/base_point.h new file mode 100644 index 0000000000..363ab1f919 --- /dev/null +++ b/engines/wintermute/base/base_point.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPOINT_H +#define WINTERMUTE_BPOINT_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBPoint: public CBBase { +public: + DECLARE_PERSISTENT(CBPoint, CBBase) + CBPoint(); + CBPoint(int initX, int initY); + int y; + int x; + virtual ~CBPoint(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_quick_msg.cpp b/engines/wintermute/base/base_quick_msg.cpp new file mode 100644 index 0000000000..ac1001a2fe --- /dev/null +++ b/engines/wintermute/base/base_quick_msg.cpp @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/base_quick_msg.h" +#include "engines/wintermute/base/base_game.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBQuickMsg::CBQuickMsg(CBGame *inGame, const char *text): CBBase(inGame) { + _text = new char [strlen(text) + 1]; + if (_text) strcpy(_text, text); + _startTime = _gameRef->_currentTime; +} + + +////////////////////////////////////////////////////////////////////////// +CBQuickMsg::~CBQuickMsg() { + if (_text) delete [] _text; +} + + +////////////////////////////////////////////////////////////////////////// +char *CBQuickMsg::getText() { + return _text; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_quick_msg.h b/engines/wintermute/base/base_quick_msg.h new file mode 100644 index 0000000000..9a68929932 --- /dev/null +++ b/engines/wintermute/base/base_quick_msg.h @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BQUICKMSG_H +#define WINTERMUTE_BQUICKMSG_H + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBQuickMsg : public CBBase { +public: + char *getText(); + uint32 _startTime; + char *_text; + CBQuickMsg(CBGame *inGame, const char *Text); + virtual ~CBQuickMsg(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_region.cpp b/engines/wintermute/base/base_region.cpp new file mode 100644 index 0000000000..3e513f9fb8 --- /dev/null +++ b/engines/wintermute/base/base_region.cpp @@ -0,0 +1,508 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CBRegion, false) + +////////////////////////////////////////////////////////////////////////// +CBRegion::CBRegion(CBGame *inGame): CBObject(inGame) { + _active = true; + _editorSelectedPoint = -1; + _lastMimicScale = -1; + _lastMimicX = _lastMimicY = INT_MIN; + + CBPlatform::setRectEmpty(&_rect); +} + + +////////////////////////////////////////////////////////////////////////// +CBRegion::~CBRegion() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBRegion::cleanup() { + for (int i = 0; i < _points.getSize(); i++) delete _points[i]; + _points.removeAll(); + + CBPlatform::setRectEmpty(&_rect); + _editorSelectedPoint = -1; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::createRegion() { + return DID_SUCCEED(getBoundingRect(&_rect)); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::pointInRegion(int x, int y) { + if (_points.getSize() < 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 (CBPlatform::ptInRect(&_rect, pt)) return ptInPolygon(x, y); + else return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CBRegion::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CBRegion::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; + CBParser parser(_gameRef); + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_REGION) { + _gameRef->LOG(0, "'REGION' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + int i; + + for (i = 0; i < _points.getSize(); i++) delete _points[i]; + _points.removeAll(); + + 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 CBPoint(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 CBRegion::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CBPoint(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 < _points.getSize()) { + _points.insertAt(Index, new CBPoint(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 < _points.getSize()) { + _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 < _points.getSize()) { + delete _points[index]; + _points[index] = NULL; + + _points.removeAt(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 < _points.getSize()) { + CScValue *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 CBObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBRegion::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(_name); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Active") == 0) { + _scValue->setBool(_active); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumPoints + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumPoints") == 0) { + _scValue->setInt(_points.getSize()); + return _scValue; + } + + else return CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBRegion::scToString() { + return "[region]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::saveAsText(CBDynBuffer *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", _name); + 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); + + int i; + + for (i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + for (i = 0; i < _points.getSize(); 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 CBRegion::persist(CBPersistMgr *persistMgr) { + + CBObject::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 CBRegion::ptInPolygon(int x, int y) { + if (_points.getSize() < 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 (int i = 1; i <= _points.getSize(); i++) { + p2.x = (double)_points[i % _points.getSize()]->x; + p2.y = (double)_points[i % _points.getSize()]->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 CBRegion::getBoundingRect(Rect32 *rect) { + if (_points.getSize() == 0) CBPlatform::setRectEmpty(rect); + else { + int MinX = INT_MAX, MinY = INT_MAX, MaxX = INT_MIN, MaxY = INT_MIN; + + for (int i = 0; i < _points.getSize(); 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); + } + CBPlatform::setRect(rect, MinX, MinY, MaxX, MaxY); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::mimic(CBRegion *region, float scale, int x, int y) { + if (scale == _lastMimicScale && x == _lastMimicX && y == _lastMimicY) return STATUS_OK; + + cleanup(); + + for (int i = 0; i < region->_points.getSize(); 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 CBPoint(xVal + x, yVal + y)); + } + + _lastMimicScale = scale; + _lastMimicX = x; + _lastMimicY = y; + + return createRegion() ? STATUS_OK : STATUS_FAILED; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_region.h b/engines/wintermute/base/base_region.h new file mode 100644 index 0000000000..5de1fb9eef --- /dev/null +++ b/engines/wintermute/base/base_region.h @@ -0,0 +1,68 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BREGION_H +#define WINTERMUTE_BREGION_H + +#include "engines/wintermute/base/base_Point.h" +#include "engines/wintermute/base/base_object.h" + +namespace WinterMute { + +class CBRegion : public CBObject { +public: + float _lastMimicScale; + int _lastMimicX; + int _lastMimicY; + void cleanup(); + bool mimic(CBRegion *region, float scale = 100.0f, int x = 0, int y = 0); + bool getBoundingRect(Rect32 *rect); + bool ptInPolygon(int x, int y); + DECLARE_PERSISTENT(CBRegion, CBObject) + bool _active; + int _editorSelectedPoint; + CBRegion(CBGame *inGame); + virtual ~CBRegion(); + bool pointInRegion(int x, int y); + bool createRegion(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + Rect32 _rect; + CBArray _points; + virtual bool saveAsText(CBDynBuffer *buffer, int indent, const char *nameOverride = NULL); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_registry.cpp b/engines/wintermute/base/base_registry.cpp new file mode 100644 index 0000000000..350a34b61e --- /dev/null +++ b/engines/wintermute/base/base_registry.cpp @@ -0,0 +1,257 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/tinyxml/tinyxml.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_registry.h" +#include "engines/wintermute/utils/path_util.h" +#include "engines/wintermute/utils/string_util.h" +#include "engines/wintermute/utils/utils.h" +#include "common/config-manager.h" +#include "common/file.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBRegistry::CBRegistry(CBGame *inGame): CBBase(inGame) { + _iniName = NULL; + + setIniName("./wme.ini"); + loadValues(true); +} + + +////////////////////////////////////////////////////////////////////////// +CBRegistry::~CBRegistry() { + saveValues(); + delete[] _iniName; + _iniName = NULL; +} + + + +////////////////////////////////////////////////////////////////////////// +AnsiString CBRegistry::readString(const AnsiString &subKey, const AnsiString &key, const AnsiString &init) { + AnsiString ret = ""; + + bool found = false; + ret = getValue(_localValues, subKey, key, found); + if (!found) ret = getValue(_values, subKey, key, found); + if (!found) ret = init; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::writeString(const AnsiString &subKey, const AnsiString &key, const AnsiString &value) { + _values[subKey][key] = value; + return true; +} + + +////////////////////////////////////////////////////////////////////////// +int CBRegistry::readInt(const AnsiString &subKey, const AnsiString &key, int init) { + if (subKey == "Audio") { + if (key == "MasterVolume") { + if (ConfMan.hasKey("master_volume")) { + return ConfMan.getInt("master_volume"); + } else { + return init; + } + } else if (key == "SFXVolume") { + if (ConfMan.hasKey("sfx_volume")) { + error("This key shouldn't be read by the scripts"); + } else { + return init; + } + } else if (key == "SpeechVolume") { + if (ConfMan.hasKey("speech_volume")) { + error("This key shouldn't be read by the scripts"); + } else { + return init; + } + } else if (key == "MusicVolume") { + if (ConfMan.hasKey("music_volume")) { + error("This key shouldn't be read by the scripts"); + } else { + return init; + } + } + } + AnsiString val = readString(subKey, key, ""); + if (val.empty()) return init; + else return atoi(val.c_str()); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::writeInt(const AnsiString &subKey, const AnsiString &key, int value) { + if (subKey == "Audio") { + if (key == "MasterVolume") { + ConfMan.setInt("master_volume", value); + return true; + } else if (key == "SFXVolume") { + error("This key shouldn't be read by the scripts"); + return true; + } else if (key == "SpeechVolume") { + error("This key shouldn't be read by the scripts"); + return true; + } else if (key == "MusicVolume") { + error("This key shouldn't be read by the scripts"); + return true; + } + } + writeString(subKey, key, StringUtil::toString(value)); + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::readBool(const AnsiString &subKey, const AnsiString &key, bool init) { + return (readInt(subKey, key, (int)init) != 0); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::writeBool(const AnsiString &subKey, const AnsiString &key, bool value) { + return writeInt(subKey, key, (int)value); +} + + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::setIniName(const char *name) { + delete[] _iniName; + _iniName = NULL; + + if (strchr(name, '\\') == NULL && strchr(name, '/') == NULL) { + _iniName = new char [strlen(name) + 3]; + sprintf(_iniName, "./%s", name); + } else { + _iniName = new char [strlen(name) + 1]; + strcpy(_iniName, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +char *CBRegistry::getIniName() { + return _iniName; +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::loadValues(bool local) { + if (local) loadXml("settings.xml", _localValues); + else loadXml(PathUtil::combine(_gameRef->getDataDir(), "settings.xml"), _values); +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::saveValues() { + saveXml(PathUtil::combine(_gameRef->getDataDir(), "settings.xml"), _values); +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::setBasePath(const char *basePath) { + _basePath = PathUtil::getFileNameWithoutExtension(basePath); + + loadValues(false); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString CBRegistry::getValue(PathValueMap &values, const AnsiString path, const AnsiString &key, bool &found) { + found = false; + PathValueMap::iterator it = values.find(path); + if (it == values.end()) return ""; + + KeyValuePair pairs = (*it)._value; + KeyValuePair::iterator keyIt = pairs.find(key); + if (keyIt == pairs.end()) return ""; + else { + found = true; + return (*keyIt)._value; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::loadXml(const AnsiString fileName, PathValueMap &values) { + TiXmlDocument doc(fileName.c_str()); + if (!doc.LoadFile()) return; + + TiXmlElement *rootElem = doc.RootElement(); + if (!rootElem || Common::String(rootElem->Value()) != "Settings") // TODO: Avoid this strcmp-use. (Hack for now, since we might drop TinyXML all together) + return; + + for (TiXmlElement *pathElem = rootElem->FirstChildElement(); pathElem != NULL; pathElem = pathElem->NextSiblingElement()) { + for (TiXmlElement *keyElem = pathElem->FirstChildElement(); keyElem != NULL; keyElem = keyElem->NextSiblingElement()) { + values[Common::String(pathElem->Value())][Common::String(keyElem->Value())] = keyElem->GetText(); + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::saveXml(const AnsiString fileName, PathValueMap &values) { + CBUtils::createPath(fileName.c_str()); + + TiXmlDocument doc; + doc.LinkEndChild(new TiXmlDeclaration("1.0", "utf-8", "")); + + TiXmlElement *root = new TiXmlElement("Settings"); + doc.LinkEndChild(root); + + PathValueMap::iterator pathIt; + for (pathIt = _values.begin(); pathIt != _values.end(); ++pathIt) { + TiXmlElement *pathElem = new TiXmlElement((*pathIt)._key.c_str()); + root->LinkEndChild(pathElem); + + + KeyValuePair pairs = (*pathIt)._value; + KeyValuePair::iterator keyIt; + for (keyIt = pairs.begin(); keyIt != pairs.end(); ++keyIt) { + TiXmlElement *keyElem = new TiXmlElement((*keyIt)._key.c_str()); + pathElem->LinkEndChild(keyElem); + + keyElem->LinkEndChild(new TiXmlText((*keyIt)._value.c_str())); + } + } + + + TiXmlPrinter printer; + doc.Accept(&printer); + + Common::DumpFile stream; + stream.open(fileName.c_str()); + + if (!stream.isOpen()) return; + else { + stream.write(printer.CStr(), printer.Size()); + stream.close(); + } +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_registry.h b/engines/wintermute/base/base_registry.h new file mode 100644 index 0000000000..06e052cd03 --- /dev/null +++ b/engines/wintermute/base/base_registry.h @@ -0,0 +1,76 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BREGISTRY_H +#define WINTERMUTE_BREGISTRY_H + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBRegistry : public CBBase { +public: + void setIniName(const char *name); + char *getIniName(); + bool writeBool(const AnsiString &subKey, const AnsiString &key, bool Value); + bool readBool(const AnsiString &subKey, const AnsiString &key, bool init = false); + bool writeInt(const AnsiString &subKey, const AnsiString &key, int value); + int readInt(const AnsiString &subKey, const AnsiString &key, int init = 0); + bool writeString(const AnsiString &subKey, const AnsiString &key, const AnsiString &value); + AnsiString readString(const AnsiString &subKey, const AnsiString &key, const AnsiString &init = ""); + CBRegistry(CBGame *inGame); + virtual ~CBRegistry(); + + void setBasePath(const char *basePath); + AnsiString getBasePath() const { + return _basePath; + } + + void loadValues(bool local); + void saveValues(); + +private: + char *_iniName; + + typedef Common::HashMap KeyValuePair; + typedef Common::HashMap PathValueMap; + + PathValueMap _localValues; + PathValueMap _values; + + AnsiString _basePath; + + void loadXml(const AnsiString fileName, PathValueMap &values); + void saveXml(const AnsiString fileName, PathValueMap &values); + + AnsiString getValue(PathValueMap &values, const AnsiString path, const AnsiString &key, bool &found); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_save_thumb_helper.cpp b/engines/wintermute/base/base_save_thumb_helper.cpp new file mode 100644 index 0000000000..bee63aa307 --- /dev/null +++ b/engines/wintermute/base/base_save_thumb_helper.cpp @@ -0,0 +1,79 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_save_thumb_helper.h" +#include "engines/wintermute/base/gfx/base_image.h" +#include "engines/wintermute/base/base_game.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbHelper::CBSaveThumbHelper(CBGame *inGame): CBBase(inGame) { + _thumbnail = NULL; +} + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbHelper::~CBSaveThumbHelper(void) { + delete _thumbnail; + _thumbnail = NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSaveThumbHelper::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(); + } + + CBImage *screenshot = _gameRef->_renderer->takeScreenshot(); + if (!screenshot) return STATUS_FAILED; + + // normal thumbnail + if (_gameRef->_thumbnailWidth > 0 && _gameRef->_thumbnailHeight > 0) { + _thumbnail = new CBImage(_gameRef); + _thumbnail->copyFrom(screenshot, _gameRef->_thumbnailWidth, _gameRef->_thumbnailHeight); + } + + + delete screenshot; + screenshot = NULL; + } + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_save_thumb_helper.h b/engines/wintermute/base/base_save_thumb_helper.h new file mode 100644 index 0000000000..e8cdbdc00d --- /dev/null +++ b/engines/wintermute/base/base_save_thumb_helper.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ +#ifndef WINTERMUTE_BSAVETHUMBHELPER_H +#define WINTERMUTE_BSAVETHUMBHELPER_H + + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBImage; + +class CBSaveThumbHelper : public CBBase { +public: + CBSaveThumbHelper(CBGame *inGame); + virtual ~CBSaveThumbHelper(void); + bool storeThumbnail(bool doFlip = false); + + CBImage *_thumbnail; + CBImage *_richThumbnail; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_script_holder.cpp b/engines/wintermute/base/base_script_holder.cpp new file mode 100644 index 0000000000..5192f76f6e --- /dev/null +++ b/engines/wintermute/base/base_script_holder.cpp @@ -0,0 +1,473 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CBScriptHolder, false) + +////////////////////////////////////////////////////////////////////// +CBScriptHolder::CBScriptHolder(CBGame *inGame): CBScriptable(inGame) { + setName(""); + + _freezable = true; + _filename = NULL; +} + + +////////////////////////////////////////////////////////////////////// +CBScriptHolder::~CBScriptHolder() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::cleanup() { + delete[] _filename; + _filename = NULL; + + int i; + + for (i = 0; i < _scripts.getSize(); i++) { + _scripts[i]->finish(true); + _scripts[i]->_owner = NULL; + } + _scripts.removeAll(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////// +void CBScriptHolder::setFilename(const char *filename) { + if (_filename != NULL) delete [] _filename; + + _filename = new char [strlen(filename) + 1]; + if (_filename != NULL) strcpy(_filename, filename); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::applyEvent(const char *eventName, bool unbreakable) { + int numHandlers = 0; + + bool ret = STATUS_FAILED; + for (int i = 0; i < _scripts.getSize(); i++) { + if (!_scripts[i]->_thread) { + CScScript *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 CBScriptHolder::listen(CBScriptHolder *param1, uint32 param2) { + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); + CScValue *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 (int i = 0; i < _scripts.getSize(); 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 (int i = 0; i < _scripts.getSize(); 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 CBScriptable::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBScriptHolder::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(_name); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Filename (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Filename") == 0) { + _scValue->setString(_filename); + return _scValue; + } + + else return CBScriptable::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::scSetProperty(const char *name, CScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + return STATUS_OK; + } else return CBScriptable::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBScriptHolder::scToString() { + return "[script_holder]"; +} + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::saveAsText(CBDynBuffer *buffer, int indent) { + return CBBase::saveAsText(buffer, indent); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::persist(CBPersistMgr *persistMgr) { + CBScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_filename)); + persistMgr->transfer(TMEMBER(_freezable)); + persistMgr->transfer(TMEMBER(_name)); + _scripts.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::addScript(const char *filename) { + for (int i = 0; i < _scripts.getSize(); i++) { + if (scumm_stricmp(_scripts[i]->_filename, filename) == 0) { + if (_scripts[i]->_state != SCRIPT_FINISHED) { + _gameRef->LOG(0, "CBScriptHolder::AddScript - trying to add script '%s' mutiple times (obj: '%s')", filename, _name); + return STATUS_OK; + } + } + } + + CScScript *scr = _gameRef->_scEngine->runScript(filename, this); + if (!scr) { + if (_gameRef->_editorForceScripts) { + // editor hack + scr = new CScScript(_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); + _gameRef->getDebugMgr()->onScriptInit(scr); + + return STATUS_OK; + } + return STATUS_FAILED; + } else { + scr->_freezable = _freezable; + _scripts.add(scr); + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::removeScript(CScScript *script) { + for (int i = 0; i < _scripts.getSize(); i++) { + if (_scripts[i] == script) { + _scripts.removeAt(i); + break; + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::canHandleEvent(const char *EventName) { + for (int i = 0; i < _scripts.getSize(); i++) { + if (!_scripts[i]->_thread && _scripts[i]->canHandleEvent(EventName)) return true; + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::canHandleMethod(const char *MethodName) { + for (int i = 0; i < _scripts.getSize(); 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 CBScriptHolder::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; + CBParser parser(_gameRef); + + 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; + } + + + CScValue *val = new CScValue(_gameRef); + val->setString(propValue); + scSetProperty(propName, val); + + delete val; + delete[] propName; + delete[] propValue; + propName = NULL; + propValue = NULL; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptHolder::makeFreezable(bool freezable) { + _freezable = freezable; + for (int i = 0; i < _scripts.getSize(); i++) + _scripts[i]->_freezable = freezable; + +} + + +////////////////////////////////////////////////////////////////////////// +CScScript *CBScriptHolder::invokeMethodThread(const char *methodName) { + for (int i = _scripts.getSize() - 1; i >= 0; i--) { + if (_scripts[i]->canHandleMethod(methodName)) { + + CScScript *thread = new CScScript(_gameRef, _scripts[i]->_engine); + if (thread) { + bool ret = thread->createMethodThread(_scripts[i], methodName); + if (DID_SUCCEED(ret)) { + _scripts[i]->_engine->_scripts.add(thread); + _gameRef->getDebugMgr()->onScriptMethodThreadInit(thread, _scripts[i], methodName); + + return thread; + } else { + delete thread; + } + } + } + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptHolder::scDebuggerDesc(char *buf, int bufSize) { + strcpy(buf, scToString()); + if (_name && strcmp(_name, "") != 0) { + strcat(buf, " Name: "); + strcat(buf, _name); + } + if (_filename) { + strcat(buf, " File: "); + strcat(buf, _filename); + } +} + + +////////////////////////////////////////////////////////////////////////// +// IWmeObject +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::sendEvent(const char *eventName) { + return DID_SUCCEED(applyEvent(eventName)); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_script_holder.h b/engines/wintermute/base/base_script_holder.h new file mode 100644 index 0000000000..0e5bc1b7ec --- /dev/null +++ b/engines/wintermute/base/base_script_holder.h @@ -0,0 +1,74 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSCRIPTHOLDER_H +#define WINTERMUTE_BSCRIPTHOLDER_H + +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base_scriptable.h" + +namespace WinterMute { + +class CBScriptHolder : public CBScriptable { +public: + DECLARE_PERSISTENT(CBScriptHolder, CBScriptable) + + CBScriptHolder(CBGame *inGame); + virtual ~CBScriptHolder(); + virtual CScScript *invokeMethodThread(const char *methodName); + virtual void makeFreezable(bool freezable); + bool canHandleEvent(const char *eventName); + virtual bool canHandleMethod(const char *eventMethod); + bool cleanup(); + bool removeScript(CScScript *script); + bool addScript(const char *filename); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + virtual bool listen(CBScriptHolder *param1, uint32 param2); + bool applyEvent(const char *eventName, bool unbreakable = false); + void setFilename(const char *filename); + bool parseProperty(byte *buffer, bool complete = true); + char *_filename; + bool _freezable; + bool _ready; + + CBArray _scripts; + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + virtual void scDebuggerDesc(char *buf, int bufSize); + // IWmeObject +public: + virtual bool sendEvent(const char *eventName); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_scriptable.cpp b/engines/wintermute/base/base_scriptable.cpp new file mode 100644 index 0000000000..e9489fa407 --- /dev/null +++ b/engines/wintermute/base/base_scriptable.cpp @@ -0,0 +1,188 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_scriptable.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBScriptable, false) + +////////////////////////////////////////////////////////////////////////// +CBScriptable::CBScriptable(CBGame *inGame, bool noValue, bool persistable): CBNamedObject(inGame) { + _refCount = 0; + + if (noValue) _scValue = NULL; + else _scValue = new CScValue(_gameRef); + + _persistable = persistable; + + _scProp = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBScriptable::~CBScriptable() { + //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 CBScriptable::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + /* + stack->correctParams(0); + stack->pushNULL(); + script->runtimeError("Call to undefined method '%s'.", name); + + return STATUS_OK; + */ + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBScriptable::scGetProperty(const char *name) { + if (!_scProp) _scProp = new CScValue(_gameRef); + if (_scProp) return _scProp->getProp(name); + else return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptable::scSetProperty(const char *name, CScValue *value) { + if (!_scProp) _scProp = new CScValue(_gameRef); + if (_scProp) return _scProp->setProp(name, value); + else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBScriptable::scToString() { + return "[native object]"; +} + +////////////////////////////////////////////////////////////////////////// +void *CBScriptable::scToMemBuffer() { + return (void *)NULL; +} + + +////////////////////////////////////////////////////////////////////////// +int CBScriptable::scToInt() { + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +double CBScriptable::scToFloat() { + return 0.0f; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptable::scToBool() { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptable::scSetString(const char *val) { +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptable::scSetInt(int val) { +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptable::scSetFloat(double val) { +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptable::scSetBool(bool val) { +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptable::persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_gameRef)); + persistMgr->transfer(TMEMBER(_refCount)); + persistMgr->transfer(TMEMBER(_scProp)); + persistMgr->transfer(TMEMBER(_scValue)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBScriptable::scCompare(CBScriptable *val) { + if (this < val) return -1; + else if (this > val) return 1; + else return 0; +} + +////////////////////////////////////////////////////////////////////////// +void CBScriptable::scDebuggerDesc(char *buf, int bufSize) { + strcpy(buf, scToString()); +} + +////////////////////////////////////////////////////////////////////////// +bool CBScriptable::canHandleMethod(const char *eventMethod) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +CScScript *CBScriptable::invokeMethodThread(const char *methodName) { + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +// IWmeDebugObject +////////////////////////////////////////////////////////////////////////// +const char *CBScriptable::dbgGetNativeClass() { + return getClassName(); +} + +////////////////////////////////////////////////////////////////////////// +IWmeDebugProp *CBScriptable::dbgGetProperty(const char *name) { + return scGetProperty(name); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_scriptable.h b/engines/wintermute/base/base_scriptable.h new file mode 100644 index 0000000000..166f3c0bd1 --- /dev/null +++ b/engines/wintermute/base/base_scriptable.h @@ -0,0 +1,90 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSCRIPTABLE_H +#define WINTERMUTE_BSCRIPTABLE_H + + +#include "engines/wintermute/base/base_named_object.h" +#include "engines/wintermute/wme_debugger.h" +#include "engines/wintermute/persistent.h" + +namespace WinterMute { + +class CScValue; +class CScStack; +class CScScript; + +class CBScriptable : public CBNamedObject, public IWmeDebugObject { +public: + virtual CScScript *invokeMethodThread(const char *methodName); + DECLARE_PERSISTENT(CBScriptable, CBNamedObject) + + CBScriptable(CBGame *inGame, bool noValue = false, bool persistable = true); + virtual ~CBScriptable(); + + // high level scripting interface + virtual bool canHandleMethod(const char *eventMethod); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual CScValue *scGetProperty(const char *name); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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(CBScriptable *val); + virtual void scDebuggerDesc(char *buf, int bufSize); + int _refCount; + CScValue *_scValue; + CScValue *_scProp; + +public: + // IWmeDebugObject + const char *dbgGetNativeClass(); + IWmeDebugProp *dbgGetProperty(const char *name); + +}; + +// Implemented in their respective .cpp-files +CBScriptable *makeSXArray(CBGame *inGame, CScStack *stack); +CBScriptable *makeSXDate(CBGame *inGame, CScStack *stack); +CBScriptable *makeSXFile(CBGame *inGame, CScStack *stack); +CBScriptable *makeSXMath(CBGame *inGame); +CBScriptable *makeSXMemBuffer(CBGame *inGame, CScStack *stack); +CBScriptable *makeSXObject(CBGame *inGame, CScStack *stack); +CBScriptable *makeSXStore(CBGame *inGame); +CBScriptable *makeSXString(CBGame *inGame, CScStack *stack); + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp new file mode 100644 index 0000000000..ba55d1b88b --- /dev/null +++ b/engines/wintermute/base/base_sprite.cpp @@ -0,0 +1,758 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_sprite.h" +#include "engines/wintermute/utils/string_util.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(CBSprite, false) + +////////////////////////////////////////////////////////////////////// +CBSprite::CBSprite(CBGame *inGame, CBObject *Owner): CBScriptHolder(inGame) { + _editorAllFrames = false; + _owner = Owner; + setDefaults(); +} + + +////////////////////////////////////////////////////////////////////// +CBSprite::~CBSprite() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBSprite::setDefaults() { + _currentFrame = -1; + _looping = false; + _lastFrameTime = 0; + _filename = 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 CBSprite::cleanup() { + CBScriptHolder::cleanup(); + + for (int i = 0; i < _frames.getSize(); i++) + delete _frames[i]; + _frames.removeAll(); + + delete[] _editorBgFile; + _editorBgFile = NULL; + + setDefaults(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSprite::draw(int x, int y, CBObject *registerOwner, float zoomX, float zoomY, uint32 alpha) { + GetCurrentFrame(zoomX, zoomY); + if (_currentFrame < 0 || _currentFrame >= _frames.getSize()) 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 CBSprite::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) { + Common::SeekableReadStream *file = _gameRef->_fileManager->openFile(filename); + if (!file) { + _gameRef->LOG(0, "CBSprite::LoadFile failed for file '%s'", filename); + if (_gameRef->_debugDebugMode) return loadFile("invalid_debug.bmp", lifeTime, cacheType); + else return loadFile("invalid.bmp", lifeTime, cacheType); + } else { + _gameRef->_fileManager->closeFile(file); + file = NULL; + } + + bool ret; + + AnsiString ext = PathUtil::getExtension(filename); + if (StringUtil::startsWith(filename, "savegame:", true) || StringUtil::compareNoCase(ext, "bmp") || StringUtil::compareNoCase(ext, "tga") || StringUtil::compareNoCase(ext, "png") || StringUtil::compareNoCase(ext, "jpg")) { + CBFrame *frame = new CBFrame(_gameRef); + CBSubFrame *subframe = new CBSubFrame(_gameRef); + subframe->setSurface(filename, true, 0, 0, 0, lifeTime, true); + if (subframe->_surface == NULL) { + _gameRef->LOG(0, "Error loading simple sprite '%s'", filename); + ret = STATUS_FAILED; + delete frame; + delete subframe; + } else { + CBPlatform::setRect(&subframe->_rect, 0, 0, subframe->_surface->getWidth(), subframe->_surface->getHeight()); + frame->_subframes.add(subframe); + _frames.add(frame); + _currentFrame = 0; + ret = STATUS_OK; + } + } else { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer) { + if (DID_FAIL(ret = loadBuffer(buffer, true, lifeTime, cacheType))) _gameRef->LOG(0, "Error parsing SPRITE file '%s'", filename); + delete [] buffer; + } + } + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, filename); + + + 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 CBSprite::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; + CBParser parser(_gameRef); + + 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; + CBFrame *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 CBFrame(_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 CBSprite::reset() { + if (_frames.getSize() > 0) _currentFrame = 0; + else _currentFrame = -1; + + killAllSounds(); + + _lastFrameTime = 0; + _finished = false; + _moveX = _moveY = 0; +} + + +////////////////////////////////////////////////////////////////////// +bool CBSprite::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 < _frames.getSize() - 1) { + _currentFrame++; + if (_continuous) _canBreak = (_currentFrame == _frames.getSize() - 1); + } else { + if (_looping) { + _currentFrame = 0; + _canBreak = true; + } else { + _finished = true; + _canBreak = true; + } + } + + _lastFrameTime = timer; + } + + _changed = (lastFrame != _currentFrame || (_looping && _frames.getSize() == 1)); + + if (_lastFrameTime == 0) { + _lastFrameTime = timer; + _changed = true; + if (_continuous) _canBreak = (_currentFrame == _frames.getSize() - 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 CBSprite::display(int X, int Y, CBObject *Register, float ZoomX, float ZoomY, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode) { + if (_currentFrame < 0 || _currentFrame >= _frames.getSize()) 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, Register, ZoomX, ZoomY, _precise, Alpha, _editorAllFrames, Rotate, BlendMode); +} + + +////////////////////////////////////////////////////////////////////////// +CBSurface *CBSprite::getSurface() { + // only used for animated textures for 3D models + if (_currentFrame < 0 || _currentFrame >= _frames.getSize()) return NULL; + CBFrame *Frame = _frames[_currentFrame]; + if (Frame && Frame->_subframes.getSize() > 0) { + CBSubFrame *Subframe = Frame->_subframes[0]; + if (Subframe) return Subframe->_surface; + else return NULL; + } else return NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSprite::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float scaleY) { + if (!rect) return false; + + CBPlatform::setRectEmpty(rect); + for (int i = 0; i < _frames.getSize(); i++) { + Rect32 frame; + Rect32 temp; + CBPlatform::copyRect(&temp, rect); + _frames[i]->getBoundingRect(&frame, x, y, scaleX, scaleY); + CBPlatform::unionRect(rect, &temp, &frame); + } + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSprite::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "SPRITE {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + 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); + } + + CBScriptHolder::saveAsText(buffer, indent + 2); + + int i; + + // scripts + for (i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + + for (i = 0; i < _frames.getSize(); i++) { + _frames[i]->saveAsText(buffer, indent + 2); + } + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSprite::persist(CBPersistMgr *persistMgr) { + CBScriptHolder::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 CBSprite::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GetFrame + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetFrame") == 0) { + stack->correctParams(1); + int Index = stack->pop()->getInt(-1); + if (Index < 0 || Index >= _frames.getSize()) { + 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); + CScValue *Val = stack->pop(); + if (Val->isInt()) { + int Index = Val->getInt(-1); + if (Index < 0 || Index >= _frames.getSize()) { + script->runtimeError("Sprite.DeleteFrame: Frame index %d is out of range.", Index); + } + } else { + CBFrame *Frame = (CBFrame *)Val->getNative(); + for (int i = 0; i < _frames.getSize(); i++) { + if (_frames[i] == Frame) { + if (i == _currentFrame) _lastFrameTime = 0; + delete _frames[i]; + _frames.removeAt(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); + CScValue *val = stack->pop(); + const char *filename = NULL; + if (!val->isNULL()) filename = val->getString(); + + CBFrame *frame = new CBFrame(_gameRef); + if (filename != NULL) { + CBSubFrame *sub = new CBSubFrame(_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; + + CScValue *val = stack->pop(); + const char *filename = NULL; + if (!val->isNULL()) + filename = val->getString(); + + CBFrame *frame = new CBFrame(_gameRef); + if (filename != NULL) { + CBSubFrame *sub = new CBSubFrame(_gameRef); + if (DID_SUCCEED(sub->setSurface(filename))) frame->_subframes.add(sub); + else delete sub; + } + + if (index >= _frames.getSize()) + _frames.add(frame); + else _frames.insertAt(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 CBScriptHolder::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBSprite::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.getSize()); + 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 CBScriptHolder::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSprite::scSetProperty(const char *name, CScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // CurrentFrame + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "CurrentFrame") == 0) { + _currentFrame = value->getInt(0); + if (_currentFrame >= _frames.getSize() || _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 CBScriptHolder::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBSprite::scToString() { + return "[sprite]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSprite::killAllSounds() { + for (int i = 0; i < _frames.getSize(); i++) { + if (_frames[i]->_sound) + _frames[i]->_sound->stop(); + } + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h new file mode 100644 index 0000000000..8f3ce84eb4 --- /dev/null +++ b/engines/wintermute/base/base_sprite.h @@ -0,0 +1,90 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSPRITE_H +#define WINTERMUTE_BSPRITE_H + + +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base_script_holder.h" + +namespace WinterMute { +class CBFrame; +class CBSurface; +class CBObject; +class CBSprite: public CBScriptHolder { +public: + bool killAllSounds(); + CBSurface *getSurface(); + char *_editorBgFile; + int _editorBgOffsetX; + int _editorBgOffsetY; + int _editorBgAlpha; + bool _streamed; + bool _streamedKeepLoaded; + void cleanup(); + void setDefaults(); + bool _precise; + DECLARE_PERSISTENT(CBSprite, CBScriptHolder) + + 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, CBObject *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(); + CBObject *_owner; + bool _changed; + bool _paused; + bool _finished; + bool loadBuffer(byte *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); + bool loadFile(const char *filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); + uint32 _lastFrameTime; + bool draw(int x, int y, CBObject *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); + CBSprite(CBGame *inGame, CBObject *owner = NULL); + virtual ~CBSprite(); + CBArray _frames; + bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_string_table.cpp b/engines/wintermute/base/base_string_table.cpp new file mode 100644 index 0000000000..c7789add9d --- /dev/null +++ b/engines/wintermute/base/base_string_table.cpp @@ -0,0 +1,229 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "engines/wintermute/utils/string_util.h" +#include "common/str.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBStringTable::CBStringTable(CBGame *inGame): CBBase(inGame) { + +} + + +////////////////////////////////////////////////////////////////////////// +CBStringTable::~CBStringTable() { + // delete strings + _strings.clear(); + +} + + +////////////////////////////////////////////////////////////////////////// +bool CBStringTable::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 = _strings.find(finalKey); + if (_stringsIter != _strings.end() && reportDuplicities) _gameRef->LOG(0, " Warning: Duplicate definition of string '%s'.", finalKey.c_str()); + + _strings[finalKey] = val; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +char *CBStringTable::getKey(const char *str) { + if (str == NULL || str[0] != '/') return NULL; + + const char *value = strchr(str + 1, '/'); + if (value == NULL) return NULL; + + char *key = new char[value - str]; + strncpy(key, str + 1, value - str - 1); + key[value - str - 1] = '\0'; + CBPlatform::strlwr(key); + + char *new_str; + + _stringsIter = _strings.find(key); + if (_stringsIter != _strings.end()) { + new_str = new char[_stringsIter->_value.size() + 1]; + strcpy(new_str, _stringsIter->_value.c_str()); + if (strlen(new_str) > 0 && new_str[0] == '/' && strchr(new_str + 1, '/')) { + delete [] key; + char *Ret = getKey(new_str); + delete [] new_str; + return Ret; + } else { + delete [] new_str; + return key; + } + } else { + return key; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBStringTable::expand(char **str, bool forceExpand) { + if (_gameRef->_doNotExpandStrings && !forceExpand) return; + + if (str == NULL || *str == NULL || *str[0] != '/') return; + + char *value = strchr(*str + 1, '/'); + if (value == NULL) return; + + char *key = new char[value - *str]; + strncpy(key, *str + 1, value - *str - 1); + key[value - *str - 1] = '\0'; + CBPlatform::strlwr(key); + + value++; + + char *new_str; + + _stringsIter = _strings.find(key); + if (_stringsIter != _strings.end()) { + new_str = new char[_stringsIter->_value.size() + 1]; + strcpy(new_str, _stringsIter->_value.c_str()); + } else { + new_str = new char[strlen(value) + 1]; + strcpy(new_str, value); + } + + delete [] key; + delete [] *str; + *str = new_str; + + if (strlen(*str) > 0 && *str[0] == '/') expand(str, forceExpand); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBStringTable::expandStatic(const char *string, bool forceExpand) { + if (_gameRef->_doNotExpandStrings && !forceExpand) return string; + + 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]; + strncpy(key, string + 1, value - string - 1); + key[value - string - 1] = '\0'; + CBPlatform::strlwr(key); + + value++; + + const char *new_str; + + _stringsIter = _strings.find(key); + if (_stringsIter != _strings.end()) { + new_str = _stringsIter->_value.c_str(); + } else { + new_str = value; + } + + delete [] key; + + if (strlen(new_str) > 0 && new_str[0] == '/') return expandStatic(new_str, forceExpand); + else return new_str; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBStringTable::loadFile(const char *filename, bool clearOld) { + _gameRef->LOG(0, "Loading string table..."); + + if (clearOld) _strings.clear(); + + uint32 size; + byte *buffer = _gameRef->_fileManager->readWholeFile(filename, &size); + if (buffer == NULL) { + _gameRef->LOG(0, "CBStringTable::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]; + strncpy(line, (char *)&buffer[pos], realLength); + line[realLength] = '\0'; + char *value = strchr(line, '\t'); + if (value == NULL) value = strchr(line, ' '); + + if (line[0] != ';') { + if (value != NULL) { + value[0] = '\0'; + value++; + for (uint32 i = 0; i < strlen(value); i++) { + if (value[i] == '|') value[i] = '\n'; + } + addString(line, value, clearOld); + } else if (line[0] != '\0') addString(line, "", clearOld); + } + + delete [] line; + pos += lineLength + 1; + } + + delete [] buffer; + + _gameRef->LOG(0, " %d strings loaded", _strings.size()); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_string_table.h b/engines/wintermute/base/base_string_table.h new file mode 100644 index 0000000000..c612c33a41 --- /dev/null +++ b/engines/wintermute/base/base_string_table.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSTRINGTABLE_H +#define WINTERMUTE_BSTRINGTABLE_H + + +#include "common/hashmap.h" +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBStringTable : public CBBase { +public: + const char *expandStatic(const char *string, bool forceExpand = false); + bool loadFile(const char *filename, bool deleteAll = true); + void expand(char **str, bool forceExpand = false); + bool addString(const char *key, const char *val, bool reportDuplicities = true); + CBStringTable(CBGame *inGame); + virtual ~CBStringTable(); + Common::HashMap _strings; + char *getKey(const char *str); +private: + Common::HashMap::iterator _stringsIter; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp new file mode 100644 index 0000000000..adce6c6b75 --- /dev/null +++ b/engines/wintermute/base/base_sub_frame.cpp @@ -0,0 +1,589 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#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(CBSubFrame, false) + +////////////////////////////////////////////////////////////////////////// +CBSubFrame::CBSubFrame(CBGame *inGame): CBScriptable(inGame, true) { + _surface = NULL; + _hotspotX = _hotspotY = 0; + _alpha = 0xFFFFFFFF; + _transparent = 0xFFFF00FF; + + CBPlatform::setRectEmpty(&_rect); + + _editorSelected = false; + + _surfaceFilename = NULL; + _cKDefault = true; + _cKRed = _cKBlue = _cKGreen = 0; + _lifeTime = -1; + _keepLoaded = false; + + _2DOnly = _3DOnly = false; + _decoration = false; + + _mirrorX = _mirrorY = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBSubFrame::~CBSubFrame() { + 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 CBSubFrame::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; + CBParser parser(_gameRef); + Rect32 rect; + int r = 255, g = 255, b = 255; + int ar = 255, ag = 255, ab = 255, alpha = 255; + bool custoTrans = false; + CBPlatform::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 (CBPlatform::isRectEmpty(&rect)) setDefaultRect(); + else _rect = rect; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +bool CBSubFrame::draw(int x, int y, CBObject *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->_rectList.add(new CBActiveRect(_gameRef, registerOwner, this, x - _hotspotX + _rect.left, y - _hotspotY + _rect.top, _rect.right - _rect.left, _rect.bottom - _rect.top, zoomX, zoomY, precise)); + } else { + _gameRef->_renderer->_rectList.add(new CBActiveRect(_gameRef, registerOwner, this, (int)(x - (_hotspotX + _rect.left) * (zoomX / 100)), (int)(y - (_hotspotY + _rect.top) * (zoomY / 100)), (int)((_rect.right - _rect.left) * (zoomX / 100)), (int)((_rect.bottom - _rect.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, _rect, zoomX, zoomY, alpha, rotate, blendMode, _mirrorX, _mirrorY); + } else { + if (zoomX == 100 && zoomY == 100) res = _surface->displayTrans(x - _hotspotX, y - _hotspotY, _rect, alpha, blendMode, _mirrorX, _mirrorY); + else res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), _rect, zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY); + } + + return res; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSubFrame::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; + + CBPlatform::setRect(rect, + (int)(x - _hotspotX * ratioX), + (int)(y - _hotspotY * ratioY), + (int)(x - _hotspotX * ratioX + (_rect.right - _rect.left) * ratioX), + (int)(y - _hotspotY * ratioY + (_rect.bottom - _rect.top) * ratioY)); + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSubFrame::saveAsText(CBDynBuffer *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; + CBPlatform::setRectEmpty(&rect); + if (_surface) CBPlatform::setRect(&rect, 0, 0, _surface->getWidth(), _surface->getHeight()); + if (!CBPlatform::equalRect(&rect, &_rect)) + buffer->putTextIndent(indent + 2, "RECT { %d,%d,%d,%d }\n", _rect.left, _rect.top, _rect.right, _rect.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"); + + CBBase::saveAsText(buffer, indent + 2); + + + if (complete) + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBSubFrame::setDefaultRect() { + if (_surface) { + CBPlatform::setRect(&_rect, 0, 0, _surface->getWidth(), _surface->getHeight()); + } else CBPlatform::setRectEmpty(&_rect); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSubFrame::persist(CBPersistMgr *persistMgr) { + + CBScriptable::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(_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 CBSubFrame::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); + CScValue *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 CBScriptable::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBSubFrame::scGetProperty(const char *name) { + if (!_scValue) _scValue = new CScValue(_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 CBScriptable::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSubFrame::scSetProperty(const char *name, CScValue *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 CBScriptable::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBSubFrame::scToString() { + return "[subframe]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSubFrame::setSurface(const char *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[strlen(filename) + 1]; + strcpy(_surfaceFilename, filename); + + _cKDefault = defaultCK; + _cKRed = ckRed; + _cKGreen = ckGreen; + _cKBlue = ckBlue; + _lifeTime = lifeTime; + _keepLoaded = keepLoaded; + + return STATUS_OK; + } else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSubFrame::setSurfaceSimple() { + if (!_surfaceFilename) { + _surface = NULL; + return STATUS_OK; + } + _surface = _gameRef->_surfaceStorage->addSurface(_surfaceFilename, _cKDefault, _cKRed, _cKGreen, _cKBlue, _lifeTime, _keepLoaded); + if (_surface) return STATUS_OK; + else return STATUS_FAILED; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h new file mode 100644 index 0000000000..6fb24c0e4f --- /dev/null +++ b/engines/wintermute/base/base_sub_frame.h @@ -0,0 +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_BSUBFRAME_H +#define WINTERMUTE_BSUBFRAME_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/base/base_scriptable.h" + +namespace WinterMute { +class CBObject; +class CBSurface; +class CBSubFrame : public CBScriptable { +public: + bool _mirrorX; + bool _mirrorY; + bool _decoration; + bool setSurface(const char *filename, bool defaultCK = true, byte ckRed = 0, byte ckGreen = 0, byte ckBlue = 0, int lifeTime = -1, bool keepLoaded = false); + bool setSurfaceSimple(); + DECLARE_PERSISTENT(CBSubFrame, CBScriptable) + void setDefaultRect(); + uint32 _transparent; + bool saveAsText(CBDynBuffer *buffer, int indent) { return saveAsText(buffer, indent, true); } + bool saveAsText(CBDynBuffer *buffer, int indent, bool complete); + bool _editorSelected; + CBSubFrame(CBGame *inGame); + virtual ~CBSubFrame(); + bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded); + bool draw(int x, int y, CBObject *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; + Rect32 _rect; + + bool _cKDefault; + byte _cKRed; + byte _cKGreen; + byte _cKBlue; + int _lifeTime; + bool _keepLoaded; + char *_surfaceFilename; + + bool _2DOnly; + bool _3DOnly; + + CBSurface *_surface; + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_surface_storage.cpp b/engines/wintermute/base/base_surface_storage.cpp new file mode 100644 index 0000000000..06c2f1b0cc --- /dev/null +++ b/engines/wintermute/base/base_surface_storage.cpp @@ -0,0 +1,189 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * 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_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(CBSurfaceStorage, true); + +////////////////////////////////////////////////////////////////////// +CBSurfaceStorage::CBSurfaceStorage(CBGame *inGame): CBBase(inGame) { + _lastCleanupTime = 0; +} + + +////////////////////////////////////////////////////////////////////// +CBSurfaceStorage::~CBSurfaceStorage() { + cleanup(true); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSurfaceStorage::cleanup(bool warn) { + for (uint32 i = 0; i < _surfaces.size(); i++) { + if (warn) _gameRef->LOG(0, "CBSurfaceStorage warning: purging surface '%s', usage:%d", _surfaces[i]->getFileName(), _surfaces[i]->_referenceCount); + delete _surfaces[i]; + } + _surfaces.clear(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSurfaceStorage::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 && _gameRef->_liveTimer - _surfaces[i]->_lastUsedTime >= _surfaces[i]->_lifeTime) { + //_gameRef->QuickMessageForm("Invalidating: %s", _surfaces[i]->_filename); + _surfaces[i]->invalidate(); + } + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +bool CBSurfaceStorage::removeSurface(CBSurface *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; +} + + +////////////////////////////////////////////////////////////////////// +CBSurface *CBSurfaceStorage::addSurface(const char *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) == 0) { + _surfaces[i]->_referenceCount++; + return _surfaces[i]; + } + } + + if (!_gameRef->_fileManager->hasFile(filename)) { + if (filename) _gameRef->LOG(0, "Missing image: '%s'", filename); + 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); + } + + CBSurface *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 CBSurfaceStorage::restoreAll() { + bool ret; + for (uint32 i = 0; i < _surfaces.size(); i++) { + ret = _surfaces[i]->restore(); + if (ret != STATUS_OK) { + _gameRef->LOG(0, "CBSurfaceStorage::RestoreAll failed"); + return ret; + } + } + return STATUS_OK; +} + + +/* +////////////////////////////////////////////////////////////////////////// +bool CBSurfaceStorage::persist(CBPersistMgr *persistMgr) +{ + + if(!persistMgr->_saving) cleanup(false); + + persistMgr->transfer(TMEMBER(_gameRef)); + + //_surfaces.persist(persistMgr); + + return STATUS_OK; +} +*/ + + +////////////////////////////////////////////////////////////////////////// +bool CBSurfaceStorage::sortSurfaces() { + qsort(&_surfaces[0], _surfaces.size(), sizeof(CBSurface *), surfaceSortCB); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBSurfaceStorage::surfaceSortCB(const void *arg1, const void *arg2) { + CBSurface *s1 = *((CBSurface **)arg1); + CBSurface *s2 = *((CBSurface **)arg2); + + // sort by life time + if (s1->_lifeTime <= 0 && s2->_lifeTime > 0) return 1; + else if (s1->_lifeTime > 0 && s2->_lifeTime <= 0) return -1; + + + // sort by validity + if (s1->_valid && !s2->_valid) return -1; + else if (!s1->_valid && s2->_valid) return 1; + + // sort by time + else if (s1->_lastUsedTime > s2->_lastUsedTime) return 1; + else if (s1->_lastUsedTime < s2->_lastUsedTime) return -1; + else return 0; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_surface_storage.h b/engines/wintermute/base/base_surface_storage.h new file mode 100644 index 0000000000..58f25e6875 --- /dev/null +++ b/engines/wintermute/base/base_surface_storage.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSURFACESTORAGE_H +#define WINTERMUTE_BSURFACESTORAGE_H + +#include "engines/wintermute/base/base.h" +#include "common/array.h" + +namespace WinterMute { +class CBSurface; +class CBSurfaceStorage : public CBBase { +public: + uint32 _lastCleanupTime; + bool initLoop(); + bool sortSurfaces(); + static int surfaceSortCB(const void *arg1, const void *arg2); + bool cleanup(bool Warn = false); + //DECLARE_PERSISTENT(CBSurfaceStorage, CBBase); + + bool restoreAll(); + CBSurface *addSurface(const char *filename, bool defaultCK = true, byte ckRed = 0, byte ckGreen = 0, byte ckBlue = 0, int lifeTime = -1, bool keepLoaded = false); + bool removeSurface(CBSurface *surface); + CBSurfaceStorage(CBGame *inGame); + virtual ~CBSurfaceStorage(); + + 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 new file mode 100644 index 0000000000..30a1a32e6a --- /dev/null +++ b/engines/wintermute/base/base_transition_manager.cpp @@ -0,0 +1,131 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/base_transition_manager.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/platform_osystem.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBTransitionMgr::CBTransitionMgr(CBGame *inGame): CBBase(inGame) { + _state = TRANS_MGR_READY; + _type = TRANSITION_NONE; + _origInteractive = false; + _preserveInteractive = false; + _lastTime = 0; + _started = false; +} + + + +////////////////////////////////////////////////////////////////////////// +CBTransitionMgr::~CBTransitionMgr() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CBTransitionMgr::isReady() { + return (_state == TRANS_MGR_READY); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBTransitionMgr::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 CBTransitionMgr::update() { + if (isReady()) return STATUS_OK; + + if (!_started) { + _started = true; + _lastTime = CBPlatform::getTime(); + } + + switch (_type) { + case TRANSITION_NONE: + _state = TRANS_MGR_READY; + break; + + case TRANSITION_FADE_OUT: { + uint32 time = CBPlatform::getTime() - _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 = CBPlatform::getTime() - _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("CBTransitionMgr::Update - unhandled enum NUM_TRANSITION_TYPES"); + } + + if (isReady()) { + if (_preserveInteractive) + _gameRef->_interactive = _origInteractive; + } + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_transition_manager.h b/engines/wintermute/base/base_transition_manager.h new file mode 100644 index 0000000000..9b84c653e9 --- /dev/null +++ b/engines/wintermute/base/base_transition_manager.h @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BTRANSITIONMGR_H +#define WINTERMUTE_BTRANSITIONMGR_H + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBTransitionMgr : public CBBase { +public: + bool _started; + uint32 _lastTime; + bool _origInteractive; + bool _preserveInteractive; + bool update(); + bool start(TTransitionType type, bool nonInteractive = false); + bool isReady(); + TTransMgrState _state; + CBTransitionMgr(CBGame *inGame); + virtual ~CBTransitionMgr(); + TTransitionType _type; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/base_viewport.cpp b/engines/wintermute/base/base_viewport.cpp new file mode 100644 index 0000000000..83cbc5b0f0 --- /dev/null +++ b/engines/wintermute/base/base_viewport.cpp @@ -0,0 +1,98 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/base/base_viewport.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBViewport, false) + +////////////////////////////////////////////////////////////////////////// +CBViewport::CBViewport(CBGame *inGame): CBBase(inGame) { + CBPlatform::setRectEmpty(&_rect); + _mainObject = NULL; + _offsetX = _offsetY = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBViewport::~CBViewport() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CBViewport::persist(CBPersistMgr *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 CBViewport::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); + } + + CBPlatform::setRect(&_rect, left, top, right, bottom); + _offsetX = left; + _offsetY = top; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +Rect32 *CBViewport::getRect() { + return &_rect; +} + + +////////////////////////////////////////////////////////////////////////// +int CBViewport::getWidth() { + return _rect.right - _rect.left; +} + + +////////////////////////////////////////////////////////////////////////// +int CBViewport::getHeight() { + return _rect.bottom - _rect.top; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/base_viewport.h b/engines/wintermute/base/base_viewport.h new file mode 100644 index 0000000000..795e6f404f --- /dev/null +++ b/engines/wintermute/base/base_viewport.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BVIEWPORT_H +#define WINTERMUTE_BVIEWPORT_H + + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { +class CBObject; +class CBViewport : public CBBase { +public: + int getHeight(); + int getWidth(); + Rect32 *getRect(); + bool setRect(int left, int top, int right, int bottom, bool noCheck = false); + DECLARE_PERSISTENT(CBViewport, CBBase) + int _offsetY; + int _offsetX; + CBObject *_mainObject; + CBViewport(CBGame *inGame = NULL); + virtual ~CBViewport(); +private: + Rect32 _rect; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/file/BDiskFile.cpp b/engines/wintermute/base/file/BDiskFile.cpp deleted file mode 100644 index 739eafcc73..0000000000 --- a/engines/wintermute/base/file/BDiskFile.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/wintypes.h" -#include "engines/wintermute/base/file/BPkgFile.h" -#include "engines/wintermute/base/file/BDiskFile.h" -#include "engines/wintermute/base/BFileManager.h" -#include "common/stream.h" -#include "common/memstream.h" -#include "common/file.h" -#include "common/zlib.h" - -namespace WinterMute { - -void correctSlashes(char *fileName) { - for (size_t i = 0; i < strlen(fileName); i++) { - if (fileName[i] == '\\') fileName[i] = '/'; - } -} - -Common::SeekableReadStream *openDiskFile(const Common::String &filename, CBFileManager *fileManager) { - char fullPath[MAX_PATH_LENGTH]; - uint32 prefixSize = 0; - Common::SeekableReadStream *file = NULL; - - for (uint32 i = 0; i < fileManager->_singlePaths.size(); i++) { - sprintf(fullPath, "%s%s", fileManager->_singlePaths[i], filename.c_str()); - correctSlashes(fullPath); - Common::File *tempFile = new Common::File(); - if (tempFile->open(fullPath)) { - file = tempFile; - } else { - delete tempFile; - } - } - - // if we didn't find it in search paths, try to open directly - if (!file) { - strcpy(fullPath, filename.c_str()); - correctSlashes(fullPath); - - Common::File *tempFile = new Common::File(); - if (tempFile->open(fullPath)) { - file = tempFile; - } else { - delete tempFile; - } - } - - 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/BDiskFile.h b/engines/wintermute/base/file/BDiskFile.h deleted file mode 100644 index 23e1a0a315..0000000000 --- a/engines/wintermute/base/file/BDiskFile.h +++ /dev/null @@ -1,42 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BDISKFILE_H -#define WINTERMUTE_BDISKFILE_H - -namespace Common { -class SeekableReadStream; -} - -namespace WinterMute { - -Common::SeekableReadStream *openDiskFile(const Common::String &filename, CBFileManager *fileManager); - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/file/BFile.cpp b/engines/wintermute/base/file/BFile.cpp deleted file mode 100644 index 911039e36d..0000000000 --- a/engines/wintermute/base/file/BFile.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFile.h" -#include "common/memstream.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////// -CBFile::CBFile(CBGame *inGame): CBBase(inGame) { - _pos = 0; - _size = 0; -} - - -////////////////////////////////////////////////////////////////////////// -CBFile::~CBFile() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFile::isEOF() { - return _pos == _size; -} - -Common::SeekableReadStream *CBFile::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/BFile.h b/engines/wintermute/base/file/BFile.h deleted file mode 100644 index d1737df0ce..0000000000 --- a/engines/wintermute/base/file/BFile.h +++ /dev/null @@ -1,67 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFILE_H -#define WINTERMUTE_BFILE_H - - -#include "engines/wintermute/base/BBase.h" -#include "common/str.h" -#include "common/stream.h" - -namespace Common { -class SeekableReadStream; -} - -namespace WinterMute { - -class CBFile : public CBBase { -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(); - CBFile(CBGame *inGame); - virtual ~CBFile(); - // Temporary solution to allow usage in ScummVM-code: - virtual Common::SeekableReadStream *getMemStream(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/file/BFileEntry.cpp b/engines/wintermute/base/file/BFileEntry.cpp deleted file mode 100644 index b00ecb6f9d..0000000000 --- a/engines/wintermute/base/file/BFileEntry.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFileEntry.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CBFileEntry::CBFileEntry(CBGame *inGame): CBBase(inGame) { - _package = NULL; - _length = _compressedLength = _offset = _flags = 0; - _filename = ""; - - _timeDate1 = _timeDate2 = 0; - - _journalTime = 0; -} - - -////////////////////////////////////////////////////////////////////////// -CBFileEntry::~CBFileEntry() { - _package = NULL; // ref only -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/BFileEntry.h b/engines/wintermute/base/file/BFileEntry.h deleted file mode 100644 index 5fdf2b6308..0000000000 --- a/engines/wintermute/base/file/BFileEntry.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFILEENTRY_H -#define WINTERMUTE_BFILEENTRY_H - - -#include "engines/wintermute/base/BBase.h" - -namespace WinterMute { - -class CBPackage; - -class CBFileEntry : public CBBase { -public: - uint32 _timeDate2; - uint32 _timeDate1; - uint32 _flags; - uint32 _journalTime; - Common::String _filename; - uint32 _compressedLength; - uint32 _length; - uint32 _offset; - CBPackage *_package; - CBFileEntry(CBGame *inGame); - virtual ~CBFileEntry(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/file/BPackage.cpp b/engines/wintermute/base/file/BPackage.cpp deleted file mode 100644 index bddf1abc1e..0000000000 --- a/engines/wintermute/base/file/BPackage.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BPackage.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "common/file.h" -#include "common/stream.h" - -namespace WinterMute { -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////// -CBPackage::CBPackage(CBGame *inGame): CBBase(inGame) { - _file = NULL; - _name = NULL; - _cD = 0; - _priority = 0; - _boundToExe = false; -} - - -////////////////////////////////////////////////////////////////////////// -CBPackage::~CBPackage() { - if (_name) delete [] _name; - closeFilePointer(_file); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBPackage::open() { - if (_file) return STATUS_OK; - else { - _file = getFilePointer(); - return _file ? STATUS_OK : STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CBPackage::close() { - delete _file; - _file = NULL; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBPackage::read(Common::SeekableReadStream *file, uint32 offset, byte *buffer, uint32 size) { - bool ret; - if (DID_FAIL(ret = open())) return ret; - else { - if (file->seek(offset, SEEK_SET)) return STATUS_FAILED; - if (file->read(buffer, size) != 1) return STATUS_FAILED; - else return STATUS_OK; - } -} - -////////////////////////////////////////////////////////////////////////// -Common::SeekableReadStream *CBPackage::getFilePointer() { - Common::File *file = _gameRef->_fileManager->openPackage(_name); - if (!file) { - _gameRef->_fileManager->requestCD(_cD, _name, ""); - file = _gameRef->_fileManager->openPackage(_name); - } - return file; -} - -////////////////////////////////////////////////////////////////////////// -void CBPackage::closeFilePointer(Common::SeekableReadStream *&file) { - delete file; - file = NULL; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/BPackage.h b/engines/wintermute/base/file/BPackage.h deleted file mode 100644 index 8c803fddd9..0000000000 --- a/engines/wintermute/base/file/BPackage.h +++ /dev/null @@ -1,61 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BPACKAGE_H -#define WINTERMUTE_BPACKAGE_H - - -#include "engines/wintermute/base/BBase.h" - -namespace Common { -class SeekableReadStream; -} - -namespace WinterMute { - -class CBPackage : public CBBase { -public: - Common::SeekableReadStream *getFilePointer(); - void closeFilePointer(Common::SeekableReadStream *&file); - - bool _boundToExe; - byte _priority; - bool read(Common::SeekableReadStream *file, uint32 offset, byte *buffer, uint32 size); - bool close(); - bool open(); - char *_name; - int _cD; - Common::SeekableReadStream *_file; - CBPackage(CBGame *inGame); - virtual ~CBPackage(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/file/BPkgFile.cpp b/engines/wintermute/base/file/BPkgFile.cpp index b787851290..3acde9c1ff 100644 --- a/engines/wintermute/base/file/BPkgFile.cpp +++ b/engines/wintermute/base/file/BPkgFile.cpp @@ -27,10 +27,10 @@ */ #include "engines/wintermute/dcgf.h" -#include "engines/wintermute/base/file/BPackage.h" +#include "engines/wintermute/base/file/base_package.h" #include "engines/wintermute/base/file/BPkgFile.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_file_manager.h" #include "common/util.h" #include "common/file.h" #include "common/stream.h" diff --git a/engines/wintermute/base/file/BPkgFile.h b/engines/wintermute/base/file/BPkgFile.h index dc8b4b684f..4356ae5519 100644 --- a/engines/wintermute/base/file/BPkgFile.h +++ b/engines/wintermute/base/file/BPkgFile.h @@ -29,7 +29,10 @@ #ifndef WINTERMUTE_BPKGFILE_H #define WINTERMUTE_BPKGFILE_H -#include "engines/wintermute/base/file/BFileEntry.h" +#include "engines/wintermute/base/file/base_file_entry.h" + +// This file is only needed until the next merge/rebase, as wrapCompressedStream now can set a known size +// as such it is not renamed to follow the convention of the rest of the files. namespace Common { class SeekableReadStream; diff --git a/engines/wintermute/base/file/BSaveThumbFile.cpp b/engines/wintermute/base/file/BSaveThumbFile.cpp deleted file mode 100644 index 4a75b7d7ce..0000000000 --- a/engines/wintermute/base/file/BSaveThumbFile.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/base/file/BSaveThumbFile.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////// -CBSaveThumbFile::CBSaveThumbFile(CBGame *inGame): CBFile(inGame) { - _data = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CBSaveThumbFile::~CBSaveThumbFile() { - close(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSaveThumbFile::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; - - char slotFilename[MAX_PATH_LENGTH + 1]; - _gameRef->getSaveSlotFilename(slot, slotFilename); - CBPersistMgr *pm = new CBPersistMgr(_gameRef); - if (!pm) return STATUS_FAILED; - - _gameRef->_debugAbsolutePathWarning = false; - if (DID_FAIL(pm->initLoad(slotFilename))) { - _gameRef->_debugAbsolutePathWarning = true; - delete pm; - return STATUS_FAILED; - } - _gameRef->_debugAbsolutePathWarning = true; - - 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 CBSaveThumbFile::close() { - delete[] _data; - _data = NULL; - - _pos = 0; - _size = 0; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBSaveThumbFile::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 CBSaveThumbFile::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/BSaveThumbFile.h b/engines/wintermute/base/file/BSaveThumbFile.h deleted file mode 100644 index 5d33ac2220..0000000000 --- a/engines/wintermute/base/file/BSaveThumbFile.h +++ /dev/null @@ -1,52 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BSAVETHUMBFILE_H -#define WINTERMUTE_BSAVETHUMBFILE_H - - -#include "engines/wintermute/base/file/BFile.h" - -namespace WinterMute { - -//TODO: Get rid of this -class CBSaveThumbFile : public CBFile { -public: - CBSaveThumbFile(CBGame *Game); - virtual ~CBSaveThumbFile(); - 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/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp new file mode 100644 index 0000000000..99bf9cff3f --- /dev/null +++ b/engines/wintermute/base/file/base_disk_file.cpp @@ -0,0 +1,131 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/wintypes.h" +#include "engines/wintermute/base/file/BPkgFile.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" + +namespace WinterMute { + +void correctSlashes(char *fileName) { + for (size_t i = 0; i < strlen(fileName); i++) { + if (fileName[i] == '\\') fileName[i] = '/'; + } +} + +Common::SeekableReadStream *openDiskFile(const Common::String &filename, CBFileManager *fileManager) { + char fullPath[MAX_PATH_LENGTH]; + uint32 prefixSize = 0; + Common::SeekableReadStream *file = NULL; + + for (uint32 i = 0; i < fileManager->_singlePaths.size(); i++) { + sprintf(fullPath, "%s%s", fileManager->_singlePaths[i], filename.c_str()); + correctSlashes(fullPath); + Common::File *tempFile = new Common::File(); + if (tempFile->open(fullPath)) { + file = tempFile; + } else { + delete tempFile; + } + } + + // if we didn't find it in search paths, try to open directly + if (!file) { + strcpy(fullPath, filename.c_str()); + correctSlashes(fullPath); + + Common::File *tempFile = new Common::File(); + if (tempFile->open(fullPath)) { + file = tempFile; + } else { + delete tempFile; + } + } + + if (file) { + uint32 magic1, magic2; + magic1 = file->readUint32LE(); + magic2 = file->readUint32LE(); + + bool compressed = false; + if (magic1 == DCGF_MAGIC && magic2 == COMPRESSED_FILE_MAGIC) compressed = true; + + if (compressed) { + uint32 DataOffset, CompSize, UncompSize; + DataOffset = file->readUint32LE(); + CompSize = file->readUint32LE(); + UncompSize = file->readUint32LE(); + + byte *CompBuffer = new byte[CompSize]; + if (!CompBuffer) { + error("Error allocating memory for compressed file '%s'", filename.c_str()); + delete file; + return NULL; + } + + byte *data = new byte[UncompSize]; + if (!data) { + error("Error allocating buffer for file '%s'", filename.c_str()); + delete [] CompBuffer; + delete file; + return NULL; + } + file->seek(DataOffset + prefixSize, SEEK_SET); + file->read(CompBuffer, CompSize); + + if (Common::uncompress(data, (unsigned long *)&UncompSize, CompBuffer, CompSize) != true) { + error("Error uncompressing file '%s'", filename.c_str()); + delete [] CompBuffer; + delete file; + return NULL; + } + + delete [] CompBuffer; + + return new Common::MemoryReadStream(data, UncompSize, DisposeAfterUse::YES); + delete file; + file = NULL; + } else { + file->seek(0, SEEK_SET); + return file; + } + + return file; + + } + return NULL; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/base_disk_file.h b/engines/wintermute/base/file/base_disk_file.h new file mode 100644 index 0000000000..23e1a0a315 --- /dev/null +++ b/engines/wintermute/base/file/base_disk_file.h @@ -0,0 +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_BDISKFILE_H +#define WINTERMUTE_BDISKFILE_H + +namespace Common { +class SeekableReadStream; +} + +namespace WinterMute { + +Common::SeekableReadStream *openDiskFile(const Common::String &filename, CBFileManager *fileManager); + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/file/base_file.cpp b/engines/wintermute/base/file/base_file.cpp new file mode 100644 index 0000000000..88a64cb147 --- /dev/null +++ b/engines/wintermute/base/file/base_file.cpp @@ -0,0 +1,69 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/file/base_file.h" +#include "common/memstream.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +CBFile::CBFile(CBGame *inGame): CBBase(inGame) { + _pos = 0; + _size = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBFile::~CBFile() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFile::isEOF() { + return _pos == _size; +} + +Common::SeekableReadStream *CBFile::getMemStream() { + uint32 oldPos = getPos(); + seek(0); + byte *data = new byte[getSize()]; + read(data, getSize()); + seek(oldPos); + Common::MemoryReadStream *memStream = new Common::MemoryReadStream(data, getSize(), DisposeAfterUse::YES); + return memStream; +} + + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/base_file.h b/engines/wintermute/base/file/base_file.h new file mode 100644 index 0000000000..b29fc41299 --- /dev/null +++ b/engines/wintermute/base/file/base_file.h @@ -0,0 +1,67 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFILE_H +#define WINTERMUTE_BFILE_H + + +#include "engines/wintermute/base/base.h" +#include "common/str.h" +#include "common/stream.h" + +namespace Common { +class SeekableReadStream; +} + +namespace WinterMute { + +class CBFile : public CBBase { +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(); + CBFile(CBGame *inGame); + virtual ~CBFile(); + // Temporary solution to allow usage in ScummVM-code: + virtual Common::SeekableReadStream *getMemStream(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/file/base_file_entry.cpp b/engines/wintermute/base/file/base_file_entry.cpp new file mode 100644 index 0000000000..3b6f4c7c16 --- /dev/null +++ b/engines/wintermute/base/file/base_file_entry.cpp @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/file/base_file_entry.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBFileEntry::CBFileEntry(CBGame *inGame): CBBase(inGame) { + _package = NULL; + _length = _compressedLength = _offset = _flags = 0; + _filename = ""; + + _timeDate1 = _timeDate2 = 0; + + _journalTime = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBFileEntry::~CBFileEntry() { + _package = NULL; // ref only +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/base_file_entry.h b/engines/wintermute/base/file/base_file_entry.h new file mode 100644 index 0000000000..ed80821004 --- /dev/null +++ b/engines/wintermute/base/file/base_file_entry.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFILEENTRY_H +#define WINTERMUTE_BFILEENTRY_H + + +#include "engines/wintermute/base/base.h" + +namespace WinterMute { + +class CBPackage; + +class CBFileEntry : public CBBase { +public: + uint32 _timeDate2; + uint32 _timeDate1; + uint32 _flags; + uint32 _journalTime; + Common::String _filename; + uint32 _compressedLength; + uint32 _length; + uint32 _offset; + CBPackage *_package; + CBFileEntry(CBGame *inGame); + virtual ~CBFileEntry(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp new file mode 100644 index 0000000000..fab6409c00 --- /dev/null +++ b/engines/wintermute/base/file/base_package.cpp @@ -0,0 +1,104 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_package.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "common/file.h" +#include "common/stream.h" + +namespace WinterMute { +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +CBPackage::CBPackage(CBGame *inGame): CBBase(inGame) { + _file = NULL; + _name = NULL; + _cD = 0; + _priority = 0; + _boundToExe = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBPackage::~CBPackage() { + if (_name) delete [] _name; + closeFilePointer(_file); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBPackage::open() { + if (_file) return STATUS_OK; + else { + _file = getFilePointer(); + return _file ? STATUS_OK : STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CBPackage::close() { + delete _file; + _file = NULL; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBPackage::read(Common::SeekableReadStream *file, uint32 offset, byte *buffer, uint32 size) { + bool ret; + if (DID_FAIL(ret = open())) return ret; + else { + if (file->seek(offset, SEEK_SET)) return STATUS_FAILED; + if (file->read(buffer, size) != 1) return STATUS_FAILED; + else return STATUS_OK; + } +} + +////////////////////////////////////////////////////////////////////////// +Common::SeekableReadStream *CBPackage::getFilePointer() { + Common::File *file = _gameRef->_fileManager->openPackage(_name); + if (!file) { + _gameRef->_fileManager->requestCD(_cD, _name, ""); + file = _gameRef->_fileManager->openPackage(_name); + } + return file; +} + +////////////////////////////////////////////////////////////////////////// +void CBPackage::closeFilePointer(Common::SeekableReadStream *&file) { + delete file; + file = NULL; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/base_package.h b/engines/wintermute/base/file/base_package.h new file mode 100644 index 0000000000..52fc4f9677 --- /dev/null +++ b/engines/wintermute/base/file/base_package.h @@ -0,0 +1,61 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPACKAGE_H +#define WINTERMUTE_BPACKAGE_H + + +#include "engines/wintermute/base/base.h" + +namespace Common { +class SeekableReadStream; +} + +namespace WinterMute { + +class CBPackage : public CBBase { +public: + Common::SeekableReadStream *getFilePointer(); + void closeFilePointer(Common::SeekableReadStream *&file); + + bool _boundToExe; + byte _priority; + bool read(Common::SeekableReadStream *file, uint32 offset, byte *buffer, uint32 size); + bool close(); + bool open(); + char *_name; + int _cD; + Common::SeekableReadStream *_file; + CBPackage(CBGame *inGame); + virtual ~CBPackage(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/file/base_resources.cpp b/engines/wintermute/base/file/base_resources.cpp new file mode 100644 index 0000000000..09cbae88fe --- /dev/null +++ b/engines/wintermute/base/file/base_resources.cpp @@ -0,0 +1,2820 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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 *CBResources::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; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/base_resources.h b/engines/wintermute/base/file/base_resources.h new file mode 100644 index 0000000000..6ec0541b5c --- /dev/null +++ b/engines/wintermute/base/file/base_resources.h @@ -0,0 +1,44 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BRESOURCES_H +#define WINTERMUTE_BRESOURCES_H + +#include "common/stream.h" +#include "common/str.h" + +namespace WinterMute { + +class CBResources { +public: + static Common::SeekableReadStream *getFile(const Common::String &fileName); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/file/base_save_thumb_file.cpp b/engines/wintermute/base/file/base_save_thumb_file.cpp new file mode 100644 index 0000000000..68200d3fc6 --- /dev/null +++ b/engines/wintermute/base/file/base_save_thumb_file.cpp @@ -0,0 +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/dcgf.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/file/base_save_thumb_file.h" +#include "engines/wintermute/platform_osystem.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbFile::CBSaveThumbFile(CBGame *inGame): CBFile(inGame) { + _data = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbFile::~CBSaveThumbFile() { + close(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSaveThumbFile::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; + + char slotFilename[MAX_PATH_LENGTH + 1]; + _gameRef->getSaveSlotFilename(slot, slotFilename); + CBPersistMgr *pm = new CBPersistMgr(_gameRef); + if (!pm) return STATUS_FAILED; + + _gameRef->_debugAbsolutePathWarning = false; + if (DID_FAIL(pm->initLoad(slotFilename))) { + _gameRef->_debugAbsolutePathWarning = true; + delete pm; + return STATUS_FAILED; + } + _gameRef->_debugAbsolutePathWarning = true; + + 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 CBSaveThumbFile::close() { + delete[] _data; + _data = NULL; + + _pos = 0; + _size = 0; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSaveThumbFile::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 CBSaveThumbFile::seek(uint32 pos, int whence) { + if (!_data) return STATUS_FAILED; + + uint32 newPos = 0; + + switch (whence) { + case SEEK_SET: + newPos = pos; + break; + case SEEK_END: + newPos = _size + pos; + break; + case SEEK_CUR: + newPos = _pos + pos; + break; + } + + if (newPos > _size) return STATUS_FAILED; + else _pos = newPos; + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/file/base_save_thumb_file.h b/engines/wintermute/base/file/base_save_thumb_file.h new file mode 100644 index 0000000000..42566581e2 --- /dev/null +++ b/engines/wintermute/base/file/base_save_thumb_file.h @@ -0,0 +1,52 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSAVETHUMBFILE_H +#define WINTERMUTE_BSAVETHUMBFILE_H + + +#include "engines/wintermute/base/file/base_file.h" + +namespace WinterMute { + +//TODO: Get rid of this +class CBSaveThumbFile : public CBFile { +public: + CBSaveThumbFile(CBGame *Game); + virtual ~CBSaveThumbFile(); + 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/font/BFont.cpp b/engines/wintermute/base/font/BFont.cpp deleted file mode 100644 index 5d0086c581..0000000000 --- a/engines/wintermute/base/font/BFont.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/font/BFont.h" -#include "engines/wintermute/base/font/BFontBitmap.h" -#include "engines/wintermute/base/font/BFontTT.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/BGame.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CBFont, false) - -////////////////////////////////////////////////////////////////////// -CBFont::CBFont(CBGame *inGame): CBObject(inGame) { - -} - - -////////////////////////////////////////////////////////////////////// -CBFont::~CBFont() { -} - - -////////////////////////////////////////////////////////////////////// -void CBFont::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { -} - - -////////////////////////////////////////////////////////////////////// -int CBFont::getTextHeight(byte *text, int width) { - return 0; -} - - -////////////////////////////////////////////////////////////////////// -int CBFont::getTextWidth(byte *text, int maxLength) { - return 0; -} - -/* -////////////////////////////////////////////////////////////////////// -bool CBFont::loadFile(const char * Filename) -{ - BYTE* Buffer = _gameRef->_fileManager->readWholeFile(filename); - if(Buffer==NULL){ - _gameRef->LOG(0, "CBFont::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename)+1]; - strcpy(_filename, filename); - - if(DID_FAIL(ret = loadBuffer(Buffer))) _gameRef->LOG(0, "Error parsing FONT file '%s'", filename); - - delete [] Buffer; - - return ret; -} - - -TOKEN_DEF_START - TOKEN_DEF (FONT) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////// -bool CBFont::loadBuffer(byte * Buffer) -{ - TOKEN_TABLE_START(commands) - TOKEN_TABLE (FONT) - TOKEN_TABLE_END - - char* params; - int cmd; - CBParser parser(_gameRef); - - if(parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)!=TOKEN_FONT){ - _gameRef->LOG(0, "'FONT' keyword expected."); - return STATUS_FAILED; - } - Buffer = (byte *)params; - - while ((cmd = parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)) > 0) - { - switch (cmd) - { - case TOKEN_IMAGE: - surface_file = (char*)params; - break; - - case TOKEN_TRANSPARENT: - parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - custo_trans = true; - break; - } - - - } - if (cmd == PARSERR_TOKENNOTFOUND){ - _gameRef->LOG(0, "Syntax error in FONT definition"); - return STATUS_FAILED; - } - - return STATUS_OK; -} -*/ - -////////////////////////////////////////////////////////////////////////// -int CBFont::getLetterHeight() { - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFont::persist(CBPersistMgr *persistMgr) { - - CBObject::persist(persistMgr); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CBFont *CBFont::createFromFile(CBGame *gameRef, const char *filename) { - if (isTrueType(gameRef, filename)) { - CBFontTT *font = new CBFontTT(gameRef); - if (font) { - if (DID_FAIL(font->loadFile(filename))) { - delete font; - return NULL; - } - } - return font; - } else { - CBFontBitmap *font = new CBFontBitmap(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 CBFont::isTrueType(CBGame *gameRef, const char *filename) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(FONT) - TOKEN_TABLE(TTFONT) - TOKEN_TABLE_END - - - byte *buffer = gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) return false; - - byte *WorkBuffer = buffer; - - char *params; - CBParser parser(gameRef); - - 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/BFont.h b/engines/wintermute/base/font/BFont.h deleted file mode 100644 index a6ab757b0d..0000000000 --- a/engines/wintermute/base/font/BFont.h +++ /dev/null @@ -1,61 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONT_H -#define WINTERMUTE_BFONT_H - -#include "engines/wintermute/base/BObject.h" - -#define NUM_CHARACTERS 256 - -namespace WinterMute { - -class CBFont: public CBObject { -public: - DECLARE_PERSISTENT(CBFont, CBObject) - virtual int getTextWidth(byte *text, int maxLength = -1); - virtual int getTextHeight(byte *text, int width); - virtual void drawText(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() {}; - CBFont(CBGame *inGame); - virtual ~CBFont(); - - static CBFont *createFromFile(CBGame *game, const char *filename); - -private: - //bool loadBuffer(byte * Buffer); - //bool loadFile(const char* Filename); - static bool isTrueType(CBGame *game, const char *filename); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/font/BFontBitmap.cpp b/engines/wintermute/base/font/BFontBitmap.cpp deleted file mode 100644 index 62576cdfea..0000000000 --- a/engines/wintermute/base/font/BFontBitmap.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/font/BFontBitmap.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BFrame.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSubFrame.h" -#include "engines/wintermute/base/BFrame.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CBFontBitmap, false) - -////////////////////////////////////////////////////////////////////// -CBFontBitmap::CBFontBitmap(CBGame *inGame): CBFont(inGame) { - _subframe = NULL; - _sprite = NULL; - _widthsFrame = 0; - memset(_widths, 0, NUM_CHARACTERS); - _tileWidth = _tileHeight = _numColumns = 0; - _fontextFix = false; - _freezable = false; - _wholeCell = false; -} - - -////////////////////////////////////////////////////////////////////// -CBFontBitmap::~CBFontBitmap() { - delete _subframe; - delete _sprite; - _subframe = NULL; - _sprite = NULL; -} - - -////////////////////////////////////////////////////////////////////// -void CBFontBitmap::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { - textHeightDraw(text, x, y, width, align, true, max_height, maxLength); -} - - -////////////////////////////////////////////////////////////////////// -int CBFontBitmap::getTextHeight(byte *text, int width) { - return textHeightDraw(text, 0, 0, width, TAL_LEFT, false); -} - - -////////////////////////////////////////////////////////////////////// -int CBFontBitmap::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; i < str.size(); i++) { - textWidth += getCharWidth(str[i]); - } - - return textWidth; -} - - -////////////////////////////////////////////////////////////////////// -int CBFontBitmap::textHeightDraw(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((char *)text)); - str = StringUtil::wideToAnsi(wstr); - } else { - str = AnsiString((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 new_line = false; - bool long_line = 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; - new_line = true; - } - - if (LineLength + getCharWidth(str[index]) > width && last_end == end) { - end = index - 1; - RealLength = LineLength; - new_line = true; - long_line = true; - } - - if (str.size() == (index + 1) || (maxLength >= 0 && index == maxLength - 1)) { - done = true; - if (!new_line) { - end = index; - LineLength += getCharWidth(str[index]); - RealLength = LineLength; - } - } else LineLength += getCharWidth(str[index]); - - if ((LineLength > width) || done || new_line) { - 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("CBFontBitmap::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 (long_line) end--; - start = end + 2; - index = end + 1; - LineLength = 0; - new_line = false; - long_line = false; - NumLines++; - } - } - - if (draw) _gameRef->_renderer->endSpriteBatch(); - - return NumLines * _tileHeight; -} - - -////////////////////////////////////////////////////////////////////// -void CBFontBitmap::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]; - - CBPlatform::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 < _sprite->_frames.getSize() && _sprite->_frames[_sprite->_currentFrame]) { - if (_sprite->_frames[_sprite->_currentFrame]->_subframes.getSize() > 0) { - _sprite->_frames[_sprite->_currentFrame]->_subframes[0]->_surface->displayTrans(x, y, rect); - } - handled = true; - } - } - if (!handled && _subframe) _subframe->_surface->displayTrans(x, y, rect); -} - - -////////////////////////////////////////////////////////////////////// -bool CBFontBitmap::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CBFontBitmap::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, filename); - - if (DID_FAIL(ret = loadBuffer(buffer))) _gameRef->LOG(0, "Error parsing FONT file '%s'", filename); - - 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 CBFontBitmap::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; - CBParser parser(_gameRef); - - 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, default_width = 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", &default_width); - 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 CBSprite(_gameRef, this); - if (!_sprite || DID_FAIL(_sprite->loadFile(spriteFile))) { - delete _sprite; - _sprite = NULL; - } - } - - if (surfaceFile != NULL && !_sprite) { - _subframe = new CBSubFrame(_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] = default_width; - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFontBitmap::persist(CBPersistMgr *persistMgr) { - - CBFont::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->_saving) - persistMgr->putBytes(_widths, sizeof(_widths)); - else - persistMgr->getBytes(_widths, sizeof(_widths)); - - - persistMgr->transfer(TMEMBER(_fontextFix)); - persistMgr->transfer(TMEMBER(_wholeCell)); - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CBFontBitmap::getCharWidth(byte index) { - if (_fontextFix) index--; - return _widths[index]; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFontBitmap::getWidths() { - CBSurface *surf = NULL; - - if (_sprite) { - if (_widthsFrame >= 0 && _widthsFrame < _sprite->_frames.getSize()) { - if (_sprite->_frames[_widthsFrame] && _sprite->_frames[_widthsFrame]->_subframes.getSize() > 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 CBFontBitmap::getLetterHeight() { - return _tileHeight; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/font/BFontBitmap.h b/engines/wintermute/base/font/BFontBitmap.h deleted file mode 100644 index 17bf433f65..0000000000 --- a/engines/wintermute/base/font/BFontBitmap.h +++ /dev/null @@ -1,72 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONTBITMAP_H -#define WINTERMUTE_BFONTBITMAP_H - - -#include "engines/wintermute/base/font/BFont.h" - -namespace WinterMute { -class CBSubFrame; -class CBFontBitmap : public CBFont { -public: - DECLARE_PERSISTENT(CBFontBitmap, CBFont) - bool loadBuffer(byte *Buffer); - bool loadFile(const char *filename); - virtual int getTextWidth(byte *text, int maxLength = -1); - virtual int getTextHeight(byte *text, int width); - virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); - virtual int getLetterHeight(); - - CBFontBitmap(CBGame *inGame); - virtual ~CBFontBitmap(); - - - bool getWidths(); - CBSprite *_sprite; - int _widthsFrame; - bool _fontextFix; - int _numColumns; - int _tileHeight; - int _tileWidth; - byte _widths[NUM_CHARACTERS]; - CBSubFrame *_subframe; - bool _wholeCell; - -private: - int getCharWidth(byte index); - void drawChar(byte c, int x, int y); - - int textHeightDraw(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/BFontStorage.cpp b/engines/wintermute/base/font/BFontStorage.cpp deleted file mode 100644 index b5605cf2bc..0000000000 --- a/engines/wintermute/base/font/BFontStorage.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CBFontStorage, true) - -////////////////////////////////////////////////////////////////////////// -CBFontStorage::CBFontStorage(CBGame *inGame): CBBase(inGame) { -} - -////////////////////////////////////////////////////////////////////////// -CBFontStorage::~CBFontStorage() { - cleanup(true); -} - -////////////////////////////////////////////////////////////////////////// -bool CBFontStorage::cleanup(bool warn) { - for (int i = 0; i < _fonts.getSize(); i++) { - if (warn) _gameRef->LOG(0, "Removing orphan font '%s'", _fonts[i]->_filename); - delete _fonts[i]; - } - _fonts.removeAll(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CBFontStorage::initLoop() { - for (int i = 0; i < _fonts.getSize(); i++) { - _fonts[i]->initLoop(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -CBFont *CBFontStorage::addFont(const char *filename) { - if (!filename) return NULL; - - for (int i = 0; i < _fonts.getSize(); i++) { - if (scumm_stricmp(_fonts[i]->_filename, filename) == 0) { - _fonts[i]->_refCount++; - return _fonts[i]; - } - } - - /* - CBFont* font = new CBFont(_gameRef); - if (!font) return NULL; - - if (DID_FAIL(font->loadFile(filename))) { - delete font; - return NULL; - } - else { - font->_refCount = 1; - _fonts.add(font); - return font; - } - */ - CBFont *font = CBFont::createFromFile(_gameRef, filename); - if (font) { - font->_refCount = 1; - _fonts.add(font); - } - return font; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFontStorage::removeFont(CBFont *font) { - if (!font) return STATUS_FAILED; - - for (int i = 0; i < _fonts.getSize(); i++) { - if (_fonts[i] == font) { - _fonts[i]->_refCount--; - if (_fonts[i]->_refCount <= 0) { - delete _fonts[i]; - _fonts.removeAt(i); - } - break; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFontStorage::persist(CBPersistMgr *persistMgr) { - - if (!persistMgr->_saving) cleanup(false); - - persistMgr->transfer(TMEMBER(_gameRef)); - _fonts.persist(persistMgr); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/font/BFontStorage.h b/engines/wintermute/base/font/BFontStorage.h deleted file mode 100644 index 9759d5d25e..0000000000 --- a/engines/wintermute/base/font/BFontStorage.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONTSTORAGE_H -#define WINTERMUTE_BFONTSTORAGE_H - - -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/coll_templ.h" - -namespace WinterMute { - -class CBFont; - -class CBFontStorage : public CBBase { -public: - DECLARE_PERSISTENT(CBFontStorage, CBBase) - bool cleanup(bool warn = false); - bool removeFont(CBFont *font); - CBFont *addFont(const char *filename); - CBFontStorage(CBGame *inGame); - virtual ~CBFontStorage(); - CBArray _fonts; - bool initLoop(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/font/BFontTT.cpp b/engines/wintermute/base/font/BFontTT.cpp deleted file mode 100644 index 5f0c9fec1a..0000000000 --- a/engines/wintermute/base/font/BFontTT.cpp +++ /dev/null @@ -1,762 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BFile.h" -#include "engines/wintermute/base/font/BFontTT.h" -#include "engines/wintermute/utils/PathUtil.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/math/MathUtil.h" -#include "engines/wintermute/base/gfx/base_renderer.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.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(CBFontTT, false) - -////////////////////////////////////////////////////////////////////////// -CBFontTT::CBFontTT(CBGame *inGame): CBFont(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; - -#if 0 - _fTFace = NULL; - _fTStream = NULL; -#endif - - _ascender = _descender = _lineHeight = _pointSize = _underlinePos = 0; - _horDpi = _vertDpi = 0; - _maxCharWidth = _maxCharHeight = 0; -} - -////////////////////////////////////////////////////////////////////////// -CBFontTT::~CBFontTT(void) { - clearCache(); - - for (int i = 0; i < _layers.getSize(); i++) { - delete _layers[i]; - } - _layers.removeAll(); - - delete[] _fontFile; - _fontFile = NULL; - - delete _deletableFont; - _font = NULL; - -#if 0 - if (_fTFace) { - FT_Done_Face(_fTFace); - _fTFace = NULL; - } - delete[] _fTStream; - _fTStream = NULL; -#endif -} - - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::clearCache() { - for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - if (_cachedTexts[i]) delete _cachedTexts[i]; - _cachedTexts[i] = NULL; - } -} - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::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 CBFontTT::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 CBFontTT::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 CBFontTT::drawText(byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) { - if (text == NULL || strcmp((char *)text, "") == 0) return; - - WideString textStr = (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 - - CBRenderer *renderer = _gameRef->_renderer; - - // find cached surface, if exists - int minPriority = INT_MAX; - int minIndex = -1; - CBSurface *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 CBCachedTTFontText; - - _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; - CBPlatform::setRect(&rc, 0, 0, surface->getWidth(), surface->getHeight()); - for (int i = 0; i < _layers.getSize(); 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; - } - } - - -} - -////////////////////////////////////////////////////////////////////////// -CBSurface *CBFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { - //TextLineList lines; - // TODO - //WrapText(text, width, maxHeight, lines); - Common::Array lines; - _font->wordWrapText(text, width, lines); - - 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; - } - // TODO: This function gets called a lot, so warnings like these drown out the usefull information - static bool hasWarned = false; - if (!hasWarned) { - hasWarned = true; - warning("CBFontTT::RenderTextToTexture - Not fully ported yet"); - } - - 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, 24, 16, 8, 0)); - 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; - } - - CBSurface *retSurface = _gameRef->_renderer->createSurface(); - Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8 , 0)); - retSurface->putSurface(*convertedSurface, true); - convertedSurface->free(); - surface->free(); - delete surface; - delete convertedSurface; - return retSurface; -#if 0 //TODO - int textHeight = lines.size() * (_maxCharHeight + _ascender); - SDL_Surface *surface = SDL_CreateRGBSurface(0, width, textHeight, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); - - SDL_LockSurface(surface); - - int posY = (int)GetLineHeight() - (int)_descender; - - for (it = lines.begin(); it != lines.end(); ++it) { - TextLine *line = (*it); - int posX = 0; - - switch (align) { - case TAL_CENTER: - posX += (width - line->GetWidth()) / 2; - break; - - case TAL_RIGHT: - posX += width - line->GetWidth(); - break; - } - - - textOffset = 0; - for (size_t i = 0; i < line->GetText().size(); i++) { - wchar_t ch = line->GetText()[i]; - - GlyphInfo *glyph = _glyphCache->GetGlyph(ch); - if (!glyph) continue; - - textOffset = MAX(textOffset, glyph->GetBearingY()); - } - - - int origPosX = posX; - - wchar_t prevChar = L'\0'; - for (size_t i = 0; i < line->GetText().size(); i++) { - wchar_t ch = line->GetText()[i]; - - GlyphInfo *glyph = _glyphCache->GetGlyph(ch); - if (!glyph) continue; - - float kerning = 0; - if (prevChar != L'\0') kerning = GetKerning(prevChar, ch); - posX += (int)kerning; - - - if (glyph->GetBearingY() > 0) { - int i = 10; - } - - SDL_Rect rect; - rect.x = posX + glyph->GetBearingX(); - rect.y = posY - glyph->GetBearingY() + textOffset; - rect.w = glyph->GetImage()->w; - rect.h = glyph->GetImage()->h; - - BlitSurface(glyph->GetImage(), surface, &rect); - - prevChar = ch; - posX += (int)(glyph->GetAdvanceX()); - posY += (int)(glyph->GetAdvanceY()); - } - - if (_isUnderline) { - for (int i = origPosX; i < origPosX + line->GetWidth(); i++) { - Uint8 *buf = (Uint8 *)surface->pixels + (int)(_underlinePos + _ascender) * surface->pitch; - Uint32 *buf32 = (Uint32 *)buf; - - buf32[i] = SDL_MapRGBA(surface->format, 255, 255, 255, 255); - } - } - - SDL_UnlockSurface(surface); - - delete line; - line = NULL; - posY += GetLineHeight(); - } - - CBSurfaceOSystem *wmeSurface = new CBSurfaceOSystem(_gameRef); - if (DID_SUCCEED(wmeSurface->CreateFromSDLSurface(surface))) { - SDL_FreeSurface(surface); - return wmeSurface; - } else { - SDL_FreeSurface(surface); - delete wmeSurface; - return NULL; - } -#endif - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect) { - //SDL_BlitSurface(src, NULL, target, targetRect); - warning("CBFontTT::BlitSurface - not ported yet"); -#if 0 - for (int y = 0; y < src->h; y++) { - if (targetRect->y + y < 0 || targetRect->y + y >= target->h) continue; - - - uint8 *srcBuf = (uint8 *)src->pixels + y * src->pitch; - uint8 *tgtBuf = (uint8 *)target->pixels + (y + targetRect->y) * target->pitch; - - uint32 *srcBuf32 = (uint32 *)srcBuf; - uint32 *tgtBuf32 = (uint32 *)tgtBuf; - - for (int x = 0; x < src->w; x++) { - if (targetRect->x + x < 0 || targetRect->x + x >= target->w) continue; - - tgtBuf32[x + targetRect->x] = srcBuf32[x]; - } - } -#endif -} - -////////////////////////////////////////////////////////////////////////// -int CBFontTT::getLetterHeight() { - return (int)getLineHeight(); -} - - -////////////////////////////////////////////////////////////////////// -bool CBFontTT::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CBFontTT::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, filename); - - if (DID_FAIL(ret = loadBuffer(buffer))) _gameRef->LOG(0, "Error parsing TTFONT file '%s'", filename); - - 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 CBFontTT::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; - CBParser parser(_gameRef); - - 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: - CBUtils::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: { - CBTTFontLayer *Layer = new CBTTFontLayer; - 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.getSize() == 0) { - CBTTFontLayer *Layer = new CBTTFontLayer; - Layer->_color = BaseColor; - _layers.add(Layer); - } - - if (!_fontFile) CBUtils::setString(&_fontFile, "arial.ttf"); - - return initFont(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CBFontTT::parseLayer(CBTTFontLayer *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; - CBParser parser(_gameRef); - - 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 CBFontTT::persist(CBPersistMgr *persistMgr) { - CBFont::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->_saving) { - numLayers = _layers.getSize(); - persistMgr->transfer(TMEMBER(numLayers)); - for (int i = 0; i < numLayers; i++) _layers[i]->persist(persistMgr); - } else { - numLayers = _layers.getSize(); - persistMgr->transfer(TMEMBER(numLayers)); - for (int i = 0; i < numLayers; i++) { - CBTTFontLayer *layer = new CBTTFontLayer; - layer->persist(persistMgr); - _layers.add(layer); - } - } - - if (!persistMgr->_saving) { - for (int i = 0; i < NUM_CACHED_TEXTS; i++) _cachedTexts[i] = NULL; - _fallbackFont = _font = _deletableFont = NULL; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::afterLoad() { - initFont(); -} - -////////////////////////////////////////////////////////////////////////// -bool CBFontTT::initFont() { - if (!_fontFile) return STATUS_FAILED; - - Common::SeekableReadStream *file = _gameRef->_fileManager->openFile(_fontFile); - if (!file) { - // the requested font file is not in wme file space; try loading a system font - AnsiString fontFileName = PathUtil::combine(CBPlatform::getSystemFontPath(), PathUtil::getFileName(_fontFile)); - file = _gameRef->_fileManager->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, _fontHeight * 4 / 3); // Compensate for the difference in dpi (96 vs 72). - _font = _deletableFont; -#endif - } - if (!_font) { - _font = _fallbackFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - warning("BFontTT::InitFont - Couldn't load %s", _fontFile); - } - _lineHeight = _font->getFontHeight(); - return STATUS_OK; -#if 0 - FT_Error error; - - float vertDpi = 96.0; - float horDpi = 96.0; - - - _fTStream = (FT_Stream)new byte[sizeof(*_fTStream)]; - memset(_fTStream, 0, sizeof(*_fTStream)); - - _fTStream->read = CBFontTT::FTReadSeekProc; - _fTStream->close = CBFontTT::FTCloseProc; - _fTStream->descriptor.pointer = file; - _fTStream->size = file->GetSize(); - - FT_Open_Args args; - args.flags = FT_OPEN_STREAM; - args.stream = _fTStream; - - error = FT_Open_Face(_gameRef->_fontStorage->GetFTLibrary(), &args, 0, &_fTFace); - if (error) { - SAFE_DELETE_ARRAY(_fTStream); - _gameRef->_fileManager->closeFile(file); - return STATUS_FAILED; - } - - error = FT_Set_Char_Size(_fTFace, 0, (FT_F26Dot6)(_fontHeight * 64), (FT_UInt)horDpi, (FT_UInt)vertDpi); - if (error) { - FT_Done_Face(_fTFace); - _fTFace = NULL; - return STATUS_FAILED; - } - - // http://en.wikipedia.org/wiki/E_(typography) - float pixelsPerEm = (_fontHeight / 72.f) * vertDpi; // Size in inches * dpi - float EmsPerUnit = 1.0f / _fTFace->units_per_EM; - float pixelsPerUnit = pixelsPerEm * EmsPerUnit; - - // bounding box in pixels - float xMin = _fTFace->bbox.xMin * pixelsPerUnit; - float xMax = _fTFace->bbox.xMax * pixelsPerUnit; - float yMin = _fTFace->bbox.yMin * pixelsPerUnit; - float yMax = _fTFace->bbox.yMax * pixelsPerUnit; - - // metrics in pixels - _ascender = _fTFace->ascender * pixelsPerUnit; - _descender = - _fTFace->descender * pixelsPerUnit; - _lineHeight = MathUtil::RoundUp(_fTFace->height * pixelsPerUnit) + 2; - _underlinePos = - _fTFace->underline_position * pixelsPerUnit; - - // max character size (used for texture grid) - _maxCharWidth = (size_t)MathUtil::RoundUp(xMax - xMin); - _maxCharHeight = (size_t)MathUtil::RoundUp(yMax - yMin); - - _glyphCache = new FontGlyphCache(); - _glyphCache->Initialize(); - -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CBFontTT::measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight) { - //TextLineList lines; - // TODO: This function gets called a lot, so warnings like these drown out the usefull information - static bool hasWarned = false; - if (!hasWarned) { - hasWarned = true; - warning("Todo: Test Mesuretext"); - } - 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/BFontTT.h b/engines/wintermute/base/font/BFontTT.h deleted file mode 100644 index 9b995b293e..0000000000 --- a/engines/wintermute/base/font/BFontTT.h +++ /dev/null @@ -1,180 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BFONTTT_H -#define WINTERMUTE_BFONTTT_H - -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFont.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 CBFontTT : public CBFont { -private: - ////////////////////////////////////////////////////////////////////////// - class CBCachedTTFontText { - public: - WideString _text; - int _width; - TTextAlign _align; - int _maxHeight; - int _maxLength; - CBSurface *_surface; - int _priority; - int _textOffset; - bool _marked; - - CBCachedTTFontText() { - //_text = L""; - _text = ""; - _width = _maxHeight = _maxLength = -1; - _align = TAL_LEFT; - _surface = NULL; - _priority = -1; - _textOffset = 0; - _marked = false; - } - - virtual ~CBCachedTTFontText() { - if (_surface) delete _surface; - } - }; - -public: - ////////////////////////////////////////////////////////////////////////// - class CBTTFontLayer { - public: - CBTTFontLayer() { - _offsetX = _offsetY = 0; - _color = 0x00000000; - } - - bool persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_offsetX)); - persistMgr->transfer(TMEMBER(_offsetY)); - persistMgr->transfer(TMEMBER(_color)); - return STATUS_OK; - } - - int _offsetX; - int _offsetY; - uint32 _color; - }; - - ////////////////////////////////////////////////////////////////////////// - class TextLine { - public: - TextLine(const WideString &text, int width) { - _text = text; - _width = width; - } - - const WideString getText() const { - return _text; - } - int getWidth() const { - return _width; - } - private: - WideString _text; - int _width; - }; - typedef Common::List TextLineList; - - -public: - DECLARE_PERSISTENT(CBFontTT, CBFont) - CBFontTT(CBGame *inGame); - virtual ~CBFontTT(void); - - virtual int getTextWidth(byte *text, int maxLength = -1); - virtual int getTextHeight(byte *text, int width); - virtual void drawText(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 char *filename); - - float getLineHeight() const { - return _lineHeight; - } - - void afterLoad(); - void initLoop(); - -private: - bool parseLayer(CBTTFontLayer *layer, byte *buffer); - - void wrapText(const WideString &text, int maxWidth, int maxHeight, TextLineList &lines); - void measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight); - - CBSurface *renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset); - void blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect); - - - CBCachedTTFontText *_cachedTexts[NUM_CACHED_TEXTS]; - - bool initFont(); - - Graphics::Font *_deletableFont; - const Graphics::Font *_font; - const Graphics::Font *_fallbackFont; - - float _ascender; - float _descender; - float _lineHeight; - float _underlinePos; - float _pointSize; - float _vertDpi; - float _horDpi; - - size_t _maxCharWidth; - size_t _maxCharHeight; - -public: - bool _isBold; - bool _isItalic; - bool _isUnderline; - bool _isStriked; - int _fontHeight; - char *_fontFile; - - CBArray _layers; - void clearCache(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/font/base_font.cpp b/engines/wintermute/base/font/base_font.cpp new file mode 100644 index 0000000000..8976cfdabd --- /dev/null +++ b/engines/wintermute/base/font/base_font.cpp @@ -0,0 +1,206 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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" +#include "engines/wintermute/base/base_game.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFont, false) + +////////////////////////////////////////////////////////////////////// +CBFont::CBFont(CBGame *inGame): CBObject(inGame) { + +} + + +////////////////////////////////////////////////////////////////////// +CBFont::~CBFont() { +} + + +////////////////////////////////////////////////////////////////////// +void CBFont::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { +} + + +////////////////////////////////////////////////////////////////////// +int CBFont::getTextHeight(byte *text, int width) { + return 0; +} + + +////////////////////////////////////////////////////////////////////// +int CBFont::getTextWidth(byte *text, int maxLength) { + return 0; +} + +/* +////////////////////////////////////////////////////////////////////// +bool CBFont::loadFile(const char * Filename) +{ + BYTE* Buffer = _gameRef->_fileManager->readWholeFile(filename); + if(Buffer==NULL){ + _gameRef->LOG(0, "CBFont::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename)+1]; + strcpy(_filename, filename); + + if(DID_FAIL(ret = loadBuffer(Buffer))) _gameRef->LOG(0, "Error parsing FONT file '%s'", filename); + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START + TOKEN_DEF (FONT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +bool CBFont::loadBuffer(byte * Buffer) +{ + TOKEN_TABLE_START(commands) + TOKEN_TABLE (FONT) + TOKEN_TABLE_END + + char* params; + int cmd; + CBParser parser(_gameRef); + + if(parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)!=TOKEN_FONT){ + _gameRef->LOG(0, "'FONT' keyword expected."); + return STATUS_FAILED; + } + Buffer = (byte *)params; + + while ((cmd = parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)) > 0) + { + switch (cmd) + { + case TOKEN_IMAGE: + surface_file = (char*)params; + break; + + case TOKEN_TRANSPARENT: + parser.scanStr(params, "%d,%d,%d", &r, &g, &b); + custo_trans = true; + break; + } + + + } + if (cmd == PARSERR_TOKENNOTFOUND){ + _gameRef->LOG(0, "Syntax error in FONT definition"); + return STATUS_FAILED; + } + + return STATUS_OK; +} +*/ + +////////////////////////////////////////////////////////////////////////// +int CBFont::getLetterHeight() { + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFont::persist(CBPersistMgr *persistMgr) { + + CBObject::persist(persistMgr); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBFont *CBFont::createFromFile(CBGame *gameRef, const char *filename) { + if (isTrueType(gameRef, filename)) { + CBFontTT *font = new CBFontTT(gameRef); + if (font) { + if (DID_FAIL(font->loadFile(filename))) { + delete font; + return NULL; + } + } + return font; + } else { + CBFontBitmap *font = new CBFontBitmap(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 CBFont::isTrueType(CBGame *gameRef, const char *filename) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TTFONT) + TOKEN_TABLE_END + + + byte *buffer = gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) return false; + + byte *WorkBuffer = buffer; + + char *params; + CBParser parser(gameRef); + + 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 new file mode 100644 index 0000000000..3df3090bb9 --- /dev/null +++ b/engines/wintermute/base/font/base_font.h @@ -0,0 +1,61 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONT_H +#define WINTERMUTE_BFONT_H + +#include "engines/wintermute/base/base_object.h" + +#define NUM_CHARACTERS 256 + +namespace WinterMute { + +class CBFont: public CBObject { +public: + DECLARE_PERSISTENT(CBFont, CBObject) + virtual int getTextWidth(byte *text, int maxLength = -1); + virtual int getTextHeight(byte *text, int width); + virtual void drawText(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() {}; + CBFont(CBGame *inGame); + virtual ~CBFont(); + + static CBFont *createFromFile(CBGame *game, const char *filename); + +private: + //bool loadBuffer(byte * Buffer); + //bool loadFile(const char* Filename); + static bool isTrueType(CBGame *game, const char *filename); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/font/base_font_bitmap.cpp b/engines/wintermute/base/font/base_font_bitmap.cpp new file mode 100644 index 0000000000..ef730afb0a --- /dev/null +++ b/engines/wintermute/base/font/base_font_bitmap.cpp @@ -0,0 +1,540 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CBFontBitmap, false) + +////////////////////////////////////////////////////////////////////// +CBFontBitmap::CBFontBitmap(CBGame *inGame): CBFont(inGame) { + _subframe = NULL; + _sprite = NULL; + _widthsFrame = 0; + memset(_widths, 0, NUM_CHARACTERS); + _tileWidth = _tileHeight = _numColumns = 0; + _fontextFix = false; + _freezable = false; + _wholeCell = false; +} + + +////////////////////////////////////////////////////////////////////// +CBFontBitmap::~CBFontBitmap() { + delete _subframe; + delete _sprite; + _subframe = NULL; + _sprite = NULL; +} + + +////////////////////////////////////////////////////////////////////// +void CBFontBitmap::drawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int maxLength) { + textHeightDraw(text, x, y, width, align, true, max_height, maxLength); +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::getTextHeight(byte *text, int width) { + return textHeightDraw(text, 0, 0, width, TAL_LEFT, false); +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::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; i < str.size(); i++) { + textWidth += getCharWidth(str[i]); + } + + return textWidth; +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::textHeightDraw(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((char *)text)); + str = StringUtil::wideToAnsi(wstr); + } else { + str = AnsiString((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 new_line = false; + bool long_line = 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; + new_line = true; + } + + if (LineLength + getCharWidth(str[index]) > width && last_end == end) { + end = index - 1; + RealLength = LineLength; + new_line = true; + long_line = true; + } + + if (str.size() == (index + 1) || (maxLength >= 0 && index == maxLength - 1)) { + done = true; + if (!new_line) { + end = index; + LineLength += getCharWidth(str[index]); + RealLength = LineLength; + } + } else LineLength += getCharWidth(str[index]); + + if ((LineLength > width) || done || new_line) { + 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("CBFontBitmap::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 (long_line) end--; + start = end + 2; + index = end + 1; + LineLength = 0; + new_line = false; + long_line = false; + NumLines++; + } + } + + if (draw) _gameRef->_renderer->endSpriteBatch(); + + return NumLines * _tileHeight; +} + + +////////////////////////////////////////////////////////////////////// +void CBFontBitmap::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]; + + CBPlatform::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 < _sprite->_frames.getSize() && _sprite->_frames[_sprite->_currentFrame]) { + if (_sprite->_frames[_sprite->_currentFrame]->_subframes.getSize() > 0) { + _sprite->_frames[_sprite->_currentFrame]->_subframes[0]->_surface->displayTrans(x, y, rect); + } + handled = true; + } + } + if (!handled && _subframe) _subframe->_surface->displayTrans(x, y, rect); +} + + +////////////////////////////////////////////////////////////////////// +bool CBFontBitmap::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CBFontBitmap::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, filename); + + if (DID_FAIL(ret = loadBuffer(buffer))) _gameRef->LOG(0, "Error parsing FONT file '%s'", filename); + + 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 CBFontBitmap::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; + CBParser parser(_gameRef); + + 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, default_width = 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", &default_width); + 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 CBSprite(_gameRef, this); + if (!_sprite || DID_FAIL(_sprite->loadFile(spriteFile))) { + delete _sprite; + _sprite = NULL; + } + } + + if (surfaceFile != NULL && !_sprite) { + _subframe = new CBSubFrame(_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] = default_width; + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFontBitmap::persist(CBPersistMgr *persistMgr) { + + CBFont::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->_saving) + persistMgr->putBytes(_widths, sizeof(_widths)); + else + persistMgr->getBytes(_widths, sizeof(_widths)); + + + persistMgr->transfer(TMEMBER(_fontextFix)); + persistMgr->transfer(TMEMBER(_wholeCell)); + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBFontBitmap::getCharWidth(byte index) { + if (_fontextFix) index--; + return _widths[index]; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFontBitmap::getWidths() { + CBSurface *surf = NULL; + + if (_sprite) { + if (_widthsFrame >= 0 && _widthsFrame < _sprite->_frames.getSize()) { + if (_sprite->_frames[_widthsFrame] && _sprite->_frames[_widthsFrame]->_subframes.getSize() > 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 CBFontBitmap::getLetterHeight() { + return _tileHeight; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/font/base_font_bitmap.h b/engines/wintermute/base/font/base_font_bitmap.h new file mode 100644 index 0000000000..8af530cbc9 --- /dev/null +++ b/engines/wintermute/base/font/base_font_bitmap.h @@ -0,0 +1,72 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTBITMAP_H +#define WINTERMUTE_BFONTBITMAP_H + + +#include "engines/wintermute/base/font/base_font.h" + +namespace WinterMute { +class CBSubFrame; +class CBFontBitmap : public CBFont { +public: + DECLARE_PERSISTENT(CBFontBitmap, CBFont) + bool loadBuffer(byte *Buffer); + bool loadFile(const char *filename); + virtual int getTextWidth(byte *text, int maxLength = -1); + virtual int getTextHeight(byte *text, int width); + virtual void drawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1); + virtual int getLetterHeight(); + + CBFontBitmap(CBGame *inGame); + virtual ~CBFontBitmap(); + + + bool getWidths(); + CBSprite *_sprite; + int _widthsFrame; + bool _fontextFix; + int _numColumns; + int _tileHeight; + int _tileWidth; + byte _widths[NUM_CHARACTERS]; + CBSubFrame *_subframe; + bool _wholeCell; + +private: + int getCharWidth(byte index); + void drawChar(byte c, int x, int y); + + int textHeightDraw(byte *text, int x, int y, int width, TTextAlign align, bool draw, int max_height = -1, int MaxLength = -1); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/font/base_font_storage.cpp b/engines/wintermute/base/font/base_font_storage.cpp new file mode 100644 index 0000000000..13f779f2cb --- /dev/null +++ b/engines/wintermute/base/font/base_font_storage.cpp @@ -0,0 +1,135 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#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(CBFontStorage, true) + +////////////////////////////////////////////////////////////////////////// +CBFontStorage::CBFontStorage(CBGame *inGame): CBBase(inGame) { +} + +////////////////////////////////////////////////////////////////////////// +CBFontStorage::~CBFontStorage() { + cleanup(true); +} + +////////////////////////////////////////////////////////////////////////// +bool CBFontStorage::cleanup(bool warn) { + for (int i = 0; i < _fonts.getSize(); i++) { + if (warn) _gameRef->LOG(0, "Removing orphan font '%s'", _fonts[i]->_filename); + delete _fonts[i]; + } + _fonts.removeAll(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBFontStorage::initLoop() { + for (int i = 0; i < _fonts.getSize(); i++) { + _fonts[i]->initLoop(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +CBFont *CBFontStorage::addFont(const char *filename) { + if (!filename) return NULL; + + for (int i = 0; i < _fonts.getSize(); i++) { + if (scumm_stricmp(_fonts[i]->_filename, filename) == 0) { + _fonts[i]->_refCount++; + return _fonts[i]; + } + } + + /* + CBFont* font = new CBFont(_gameRef); + if (!font) return NULL; + + if (DID_FAIL(font->loadFile(filename))) { + delete font; + return NULL; + } + else { + font->_refCount = 1; + _fonts.add(font); + return font; + } + */ + CBFont *font = CBFont::createFromFile(_gameRef, filename); + if (font) { + font->_refCount = 1; + _fonts.add(font); + } + return font; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFontStorage::removeFont(CBFont *font) { + if (!font) return STATUS_FAILED; + + for (int i = 0; i < _fonts.getSize(); i++) { + if (_fonts[i] == font) { + _fonts[i]->_refCount--; + if (_fonts[i]->_refCount <= 0) { + delete _fonts[i]; + _fonts.removeAt(i); + } + break; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFontStorage::persist(CBPersistMgr *persistMgr) { + + if (!persistMgr->_saving) cleanup(false); + + persistMgr->transfer(TMEMBER(_gameRef)); + _fonts.persist(persistMgr); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/font/base_font_storage.h b/engines/wintermute/base/font/base_font_storage.h new file mode 100644 index 0000000000..7c88e9a2f4 --- /dev/null +++ b/engines/wintermute/base/font/base_font_storage.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTSTORAGE_H +#define WINTERMUTE_BFONTSTORAGE_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/coll_templ.h" + +namespace WinterMute { + +class CBFont; + +class CBFontStorage : public CBBase { +public: + DECLARE_PERSISTENT(CBFontStorage, CBBase) + bool cleanup(bool warn = false); + bool removeFont(CBFont *font); + CBFont *addFont(const char *filename); + CBFontStorage(CBGame *inGame); + virtual ~CBFontStorage(); + CBArray _fonts; + bool initLoop(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp new file mode 100644 index 0000000000..a52922fb76 --- /dev/null +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -0,0 +1,762 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CBFontTT, false) + +////////////////////////////////////////////////////////////////////////// +CBFontTT::CBFontTT(CBGame *inGame): CBFont(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; + +#if 0 + _fTFace = NULL; + _fTStream = NULL; +#endif + + _ascender = _descender = _lineHeight = _pointSize = _underlinePos = 0; + _horDpi = _vertDpi = 0; + _maxCharWidth = _maxCharHeight = 0; +} + +////////////////////////////////////////////////////////////////////////// +CBFontTT::~CBFontTT(void) { + clearCache(); + + for (int i = 0; i < _layers.getSize(); i++) { + delete _layers[i]; + } + _layers.removeAll(); + + delete[] _fontFile; + _fontFile = NULL; + + delete _deletableFont; + _font = NULL; + +#if 0 + if (_fTFace) { + FT_Done_Face(_fTFace); + _fTFace = NULL; + } + delete[] _fTStream; + _fTStream = NULL; +#endif +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::clearCache() { + for (int i = 0; i < NUM_CACHED_TEXTS; i++) { + if (_cachedTexts[i]) delete _cachedTexts[i]; + _cachedTexts[i] = NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::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 CBFontTT::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 CBFontTT::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 CBFontTT::drawText(byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) { + if (text == NULL || strcmp((char *)text, "") == 0) return; + + WideString textStr = (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 + + CBRenderer *renderer = _gameRef->_renderer; + + // find cached surface, if exists + int minPriority = INT_MAX; + int minIndex = -1; + CBSurface *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 CBCachedTTFontText; + + _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; + CBPlatform::setRect(&rc, 0, 0, surface->getWidth(), surface->getHeight()); + for (int i = 0; i < _layers.getSize(); 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; + } + } + + +} + +////////////////////////////////////////////////////////////////////////// +CBSurface *CBFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { + //TextLineList lines; + // TODO + //WrapText(text, width, maxHeight, lines); + Common::Array lines; + _font->wordWrapText(text, width, lines); + + 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; + } + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + static bool hasWarned = false; + if (!hasWarned) { + hasWarned = true; + warning("CBFontTT::RenderTextToTexture - Not fully ported yet"); + } + + 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, 24, 16, 8, 0)); + 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; + } + + CBSurface *retSurface = _gameRef->_renderer->createSurface(); + Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8 , 0)); + retSurface->putSurface(*convertedSurface, true); + convertedSurface->free(); + surface->free(); + delete surface; + delete convertedSurface; + return retSurface; +#if 0 //TODO + int textHeight = lines.size() * (_maxCharHeight + _ascender); + SDL_Surface *surface = SDL_CreateRGBSurface(0, width, textHeight, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); + + SDL_LockSurface(surface); + + int posY = (int)GetLineHeight() - (int)_descender; + + for (it = lines.begin(); it != lines.end(); ++it) { + TextLine *line = (*it); + int posX = 0; + + switch (align) { + case TAL_CENTER: + posX += (width - line->GetWidth()) / 2; + break; + + case TAL_RIGHT: + posX += width - line->GetWidth(); + break; + } + + + textOffset = 0; + for (size_t i = 0; i < line->GetText().size(); i++) { + wchar_t ch = line->GetText()[i]; + + GlyphInfo *glyph = _glyphCache->GetGlyph(ch); + if (!glyph) continue; + + textOffset = MAX(textOffset, glyph->GetBearingY()); + } + + + int origPosX = posX; + + wchar_t prevChar = L'\0'; + for (size_t i = 0; i < line->GetText().size(); i++) { + wchar_t ch = line->GetText()[i]; + + GlyphInfo *glyph = _glyphCache->GetGlyph(ch); + if (!glyph) continue; + + float kerning = 0; + if (prevChar != L'\0') kerning = GetKerning(prevChar, ch); + posX += (int)kerning; + + + if (glyph->GetBearingY() > 0) { + int i = 10; + } + + SDL_Rect rect; + rect.x = posX + glyph->GetBearingX(); + rect.y = posY - glyph->GetBearingY() + textOffset; + rect.w = glyph->GetImage()->w; + rect.h = glyph->GetImage()->h; + + BlitSurface(glyph->GetImage(), surface, &rect); + + prevChar = ch; + posX += (int)(glyph->GetAdvanceX()); + posY += (int)(glyph->GetAdvanceY()); + } + + if (_isUnderline) { + for (int i = origPosX; i < origPosX + line->GetWidth(); i++) { + Uint8 *buf = (Uint8 *)surface->pixels + (int)(_underlinePos + _ascender) * surface->pitch; + Uint32 *buf32 = (Uint32 *)buf; + + buf32[i] = SDL_MapRGBA(surface->format, 255, 255, 255, 255); + } + } + + SDL_UnlockSurface(surface); + + delete line; + line = NULL; + posY += GetLineHeight(); + } + + CBSurfaceOSystem *wmeSurface = new CBSurfaceOSystem(_gameRef); + if (DID_SUCCEED(wmeSurface->CreateFromSDLSurface(surface))) { + SDL_FreeSurface(surface); + return wmeSurface; + } else { + SDL_FreeSurface(surface); + delete wmeSurface; + return NULL; + } +#endif + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect) { + //SDL_BlitSurface(src, NULL, target, targetRect); + warning("CBFontTT::BlitSurface - not ported yet"); +#if 0 + for (int y = 0; y < src->h; y++) { + if (targetRect->y + y < 0 || targetRect->y + y >= target->h) continue; + + + uint8 *srcBuf = (uint8 *)src->pixels + y * src->pitch; + uint8 *tgtBuf = (uint8 *)target->pixels + (y + targetRect->y) * target->pitch; + + uint32 *srcBuf32 = (uint32 *)srcBuf; + uint32 *tgtBuf32 = (uint32 *)tgtBuf; + + for (int x = 0; x < src->w; x++) { + if (targetRect->x + x < 0 || targetRect->x + x >= target->w) continue; + + tgtBuf32[x + targetRect->x] = srcBuf32[x]; + } + } +#endif +} + +////////////////////////////////////////////////////////////////////////// +int CBFontTT::getLetterHeight() { + return (int)getLineHeight(); +} + + +////////////////////////////////////////////////////////////////////// +bool CBFontTT::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CBFontTT::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, filename); + + if (DID_FAIL(ret = loadBuffer(buffer))) _gameRef->LOG(0, "Error parsing TTFONT file '%s'", filename); + + 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 CBFontTT::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; + CBParser parser(_gameRef); + + 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: + CBUtils::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: { + CBTTFontLayer *Layer = new CBTTFontLayer; + 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.getSize() == 0) { + CBTTFontLayer *Layer = new CBTTFontLayer; + Layer->_color = BaseColor; + _layers.add(Layer); + } + + if (!_fontFile) CBUtils::setString(&_fontFile, "arial.ttf"); + + return initFont(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFontTT::parseLayer(CBTTFontLayer *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; + CBParser parser(_gameRef); + + 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 CBFontTT::persist(CBPersistMgr *persistMgr) { + CBFont::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->_saving) { + numLayers = _layers.getSize(); + persistMgr->transfer(TMEMBER(numLayers)); + for (int i = 0; i < numLayers; i++) _layers[i]->persist(persistMgr); + } else { + numLayers = _layers.getSize(); + persistMgr->transfer(TMEMBER(numLayers)); + for (int i = 0; i < numLayers; i++) { + CBTTFontLayer *layer = new CBTTFontLayer; + layer->persist(persistMgr); + _layers.add(layer); + } + } + + if (!persistMgr->_saving) { + for (int i = 0; i < NUM_CACHED_TEXTS; i++) _cachedTexts[i] = NULL; + _fallbackFont = _font = _deletableFont = NULL; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::afterLoad() { + initFont(); +} + +////////////////////////////////////////////////////////////////////////// +bool CBFontTT::initFont() { + if (!_fontFile) return STATUS_FAILED; + + Common::SeekableReadStream *file = _gameRef->_fileManager->openFile(_fontFile); + if (!file) { + // the requested font file is not in wme file space; try loading a system font + AnsiString fontFileName = PathUtil::combine(CBPlatform::getSystemFontPath(), PathUtil::getFileName(_fontFile)); + file = _gameRef->_fileManager->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, _fontHeight * 4 / 3); // Compensate for the difference in dpi (96 vs 72). + _font = _deletableFont; +#endif + } + if (!_font) { + _font = _fallbackFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + warning("BFontTT::InitFont - Couldn't load %s", _fontFile); + } + _lineHeight = _font->getFontHeight(); + return STATUS_OK; +#if 0 + FT_Error error; + + float vertDpi = 96.0; + float horDpi = 96.0; + + + _fTStream = (FT_Stream)new byte[sizeof(*_fTStream)]; + memset(_fTStream, 0, sizeof(*_fTStream)); + + _fTStream->read = CBFontTT::FTReadSeekProc; + _fTStream->close = CBFontTT::FTCloseProc; + _fTStream->descriptor.pointer = file; + _fTStream->size = file->GetSize(); + + FT_Open_Args args; + args.flags = FT_OPEN_STREAM; + args.stream = _fTStream; + + error = FT_Open_Face(_gameRef->_fontStorage->GetFTLibrary(), &args, 0, &_fTFace); + if (error) { + SAFE_DELETE_ARRAY(_fTStream); + _gameRef->_fileManager->closeFile(file); + return STATUS_FAILED; + } + + error = FT_Set_Char_Size(_fTFace, 0, (FT_F26Dot6)(_fontHeight * 64), (FT_UInt)horDpi, (FT_UInt)vertDpi); + if (error) { + FT_Done_Face(_fTFace); + _fTFace = NULL; + return STATUS_FAILED; + } + + // http://en.wikipedia.org/wiki/E_(typography) + float pixelsPerEm = (_fontHeight / 72.f) * vertDpi; // Size in inches * dpi + float EmsPerUnit = 1.0f / _fTFace->units_per_EM; + float pixelsPerUnit = pixelsPerEm * EmsPerUnit; + + // bounding box in pixels + float xMin = _fTFace->bbox.xMin * pixelsPerUnit; + float xMax = _fTFace->bbox.xMax * pixelsPerUnit; + float yMin = _fTFace->bbox.yMin * pixelsPerUnit; + float yMax = _fTFace->bbox.yMax * pixelsPerUnit; + + // metrics in pixels + _ascender = _fTFace->ascender * pixelsPerUnit; + _descender = - _fTFace->descender * pixelsPerUnit; + _lineHeight = MathUtil::RoundUp(_fTFace->height * pixelsPerUnit) + 2; + _underlinePos = - _fTFace->underline_position * pixelsPerUnit; + + // max character size (used for texture grid) + _maxCharWidth = (size_t)MathUtil::RoundUp(xMax - xMin); + _maxCharHeight = (size_t)MathUtil::RoundUp(yMax - yMin); + + _glyphCache = new FontGlyphCache(); + _glyphCache->Initialize(); + +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight) { + //TextLineList lines; + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + static bool hasWarned = false; + if (!hasWarned) { + hasWarned = true; + warning("Todo: Test Mesuretext"); + } + 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 new file mode 100644 index 0000000000..4d8e71a3ff --- /dev/null +++ b/engines/wintermute/base/font/base_font_truetype.h @@ -0,0 +1,180 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTTT_H +#define WINTERMUTE_BFONTTT_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 CBFontTT : public CBFont { +private: + ////////////////////////////////////////////////////////////////////////// + class CBCachedTTFontText { + public: + WideString _text; + int _width; + TTextAlign _align; + int _maxHeight; + int _maxLength; + CBSurface *_surface; + int _priority; + int _textOffset; + bool _marked; + + CBCachedTTFontText() { + //_text = L""; + _text = ""; + _width = _maxHeight = _maxLength = -1; + _align = TAL_LEFT; + _surface = NULL; + _priority = -1; + _textOffset = 0; + _marked = false; + } + + virtual ~CBCachedTTFontText() { + if (_surface) delete _surface; + } + }; + +public: + ////////////////////////////////////////////////////////////////////////// + class CBTTFontLayer { + public: + CBTTFontLayer() { + _offsetX = _offsetY = 0; + _color = 0x00000000; + } + + bool persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_offsetX)); + persistMgr->transfer(TMEMBER(_offsetY)); + persistMgr->transfer(TMEMBER(_color)); + return STATUS_OK; + } + + int _offsetX; + int _offsetY; + uint32 _color; + }; + + ////////////////////////////////////////////////////////////////////////// + class TextLine { + public: + TextLine(const WideString &text, int width) { + _text = text; + _width = width; + } + + const WideString getText() const { + return _text; + } + int getWidth() const { + return _width; + } + private: + WideString _text; + int _width; + }; + typedef Common::List TextLineList; + + +public: + DECLARE_PERSISTENT(CBFontTT, CBFont) + CBFontTT(CBGame *inGame); + virtual ~CBFontTT(void); + + virtual int getTextWidth(byte *text, int maxLength = -1); + virtual int getTextHeight(byte *text, int width); + virtual void drawText(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 char *filename); + + float getLineHeight() const { + return _lineHeight; + } + + void afterLoad(); + void initLoop(); + +private: + bool parseLayer(CBTTFontLayer *layer, byte *buffer); + + void wrapText(const WideString &text, int maxWidth, int maxHeight, TextLineList &lines); + void measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight); + + CBSurface *renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset); + void blitSurface(Graphics::Surface *src, Graphics::Surface *target, Common::Rect *targetRect); + + + CBCachedTTFontText *_cachedTexts[NUM_CACHED_TEXTS]; + + bool initFont(); + + Graphics::Font *_deletableFont; + const Graphics::Font *_font; + const Graphics::Font *_fallbackFont; + + float _ascender; + float _descender; + float _lineHeight; + float _underlinePos; + float _pointSize; + float _vertDpi; + float _horDpi; + + size_t _maxCharWidth; + size_t _maxCharHeight; + +public: + bool _isBold; + bool _isItalic; + bool _isUnderline; + bool _isStriked; + int _fontHeight; + char *_fontFile; + + CBArray _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 f1e27c9622..fb6b23db2b 100644 --- a/engines/wintermute/base/gfx/base_image.cpp +++ b/engines/wintermute/base/gfx/base_image.cpp @@ -28,10 +28,10 @@ #include "engines/wintermute/dcgf.h" #include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/graphics/transparentSurface.h" -#include "engines/wintermute/utils/StringUtil.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/graphics/transparent_surface.h" +#include "engines/wintermute/utils/string_util.h" #include "graphics/decoders/png.h" #include "graphics/decoders/jpeg.h" #include "graphics/decoders/bmp.h" diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h index 646a9ddd2d..6cda3e6b46 100644 --- a/engines/wintermute/base/gfx/base_image.h +++ b/engines/wintermute/base/gfx/base_image.h @@ -29,7 +29,7 @@ #ifndef WINTERMUTE_BIMAGE_H #define WINTERMUTE_BIMAGE_H -#include "engines/wintermute/base/BBase.h" +#include "engines/wintermute/base/base.h" #include "graphics/surface.h" #include "graphics/pixelformat.h" #include "graphics/decoders/image_decoder.h" diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp index 5c5ebd91b4..a8c19362f6 100644 --- a/engines/wintermute/base/gfx/base_renderer.cpp +++ b/engines/wintermute/base/gfx/base_renderer.cpp @@ -27,11 +27,11 @@ */ #include "engines/wintermute/dcgf.h" -#include "engines/wintermute/base/BActiveRect.h" +#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/BSubFrame.h" -#include "engines/wintermute/base/BRegion.h" +#include "engines/wintermute/base/base_sub_frame.h" +#include "engines/wintermute/base/base_region.h" #include "engines/wintermute/platform_osystem.h" namespace WinterMute { diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h index 81c13f8b39..d743f19791 100644 --- a/engines/wintermute/base/gfx/base_renderer.h +++ b/engines/wintermute/base/gfx/base_renderer.h @@ -31,7 +31,7 @@ #include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/base/BBase.h" +#include "engines/wintermute/base/base.h" #include "common/rect.h" namespace WinterMute { diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp index 6c0ca40765..73b385d180 100644 --- a/engines/wintermute/base/gfx/base_surface.cpp +++ b/engines/wintermute/base/gfx/base_surface.cpp @@ -27,7 +27,7 @@ */ #include "engines/wintermute/wintypes.h" -#include "engines/wintermute/base/BGame.h" +#include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/gfx/base_surface.h" namespace WinterMute { diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h index f5fbd495aa..22c1fb83b8 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -29,8 +29,8 @@ #ifndef WINTERMUTE_BSURFACE_H #define WINTERMUTE_BSURFACE_H -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/math/Rect32.h" +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/math/rect32.h" #include "graphics/surface.h" namespace WinterMute { diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index ee971ab6c9..dbd2511928 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -28,15 +28,15 @@ #include "engines/wintermute/dcgf.h" #include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" -#include "engines/wintermute/base/BRegistry.h" +#include "engines/wintermute/base/base_registry.h" #include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" -#include "engines/wintermute/base/BSurfaceStorage.h" +#include "engines/wintermute/base/base_surface_storage.h" #include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/math/MathUtil.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSprite.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/transparentSurface.h" +#include "engines/wintermute/graphics/transparent_surface.h" #include "common/queue.h" namespace WinterMute { diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index 66c6e4a61a..87c5731b49 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -26,9 +26,9 @@ * Copyright (c) 2011 Jan Nedoma */ -#include "engines/wintermute/base/file/BFile.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/BGame.h" +#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" @@ -36,7 +36,7 @@ #include "graphics/decoders/png.h" #include "graphics/decoders/bmp.h" #include "graphics/decoders/jpeg.h" -#include "engines/wintermute/graphics/transparentSurface.h" +#include "engines/wintermute/graphics/transparent_surface.h" #include "engines/wintermute/graphics/tga.h" #include "graphics/pixelformat.h" #include "graphics/surface.h" diff --git a/engines/wintermute/base/particles/PartEmitter.cpp b/engines/wintermute/base/particles/PartEmitter.cpp deleted file mode 100644 index 97de1fe044..0000000000 --- a/engines/wintermute/base/particles/PartEmitter.cpp +++ /dev/null @@ -1,1199 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/particles/PartEmitter.h" -#include "engines/wintermute/base/particles/PartParticle.h" -#include "engines/wintermute/math/Vector2.h" -#include "engines/wintermute/math/Matrix4.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/base/BFileManager.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(CPartEmitter, false) - -////////////////////////////////////////////////////////////////////////// -CPartEmitter::CPartEmitter(CBGame *inGame, CBScriptHolder *Owner) : CBObject(inGame) { - _width = _height = 0; - - CBPlatform::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; -} - - -////////////////////////////////////////////////////////////////////////// -CPartEmitter::~CPartEmitter(void) { - for (int i = 0; i < _particles.getSize(); i++) { - delete _particles[i]; - } - _particles.removeAll(); - - for (int i = 0; i < _forces.getSize(); i++) { - delete _forces[i]; - } - _forces.removeAll(); - - - for (int i = 0; i < _sprites.getSize(); i++) { - delete [] _sprites[i]; - } - _sprites.removeAll(); - - delete[] _emitEvent; - _emitEvent = NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::addSprite(const char *filename) { - if (!filename) return STATUS_FAILED; - - // do we already have the file? - for (int i = 0; i < _sprites.getSize(); i++) { - if (scumm_stricmp(filename, _sprites[i]) == 0) return STATUS_OK; - } - - // check if file exists - Common::SeekableReadStream *File = _gameRef->_fileManager->openFile(filename); - if (!File) { - _gameRef->LOG(0, "Sprite '%s' not found", filename); - return STATUS_FAILED; - } else _gameRef->_fileManager->closeFile(File); - - char *Str = new char[strlen(filename) + 1]; - strcpy(Str, filename); - _sprites.add(Str); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::removeSprite(const char *filename) { - for (int i = 0; i < _sprites.getSize(); i++) { - if (scumm_stricmp(filename, _sprites[i]) == 0) { - delete [] _sprites[i]; - _sprites.removeAt(i); - return STATUS_OK; - } - } - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta) { - if (!particle) return STATUS_FAILED; - if (_sprites.getSize() == 0) return STATUS_FAILED; - - int posX = CBUtils::randomInt(_posX, _posX + _width); - int posY = CBUtils::randomInt(_posY, _posY + _height); - float posZ = CBUtils::randomFloat(0.0f, 100.0f); - - float velocity; - if (_velocityZBased) velocity = _velocity1 + posZ * (_velocity2 - _velocity1) / 100; - else velocity = CBUtils::randomFloat(_velocity1, _velocity2); - - float scale; - if (_scaleZBased) scale = _scale1 + posZ * (_scale2 - _scale1) / 100; - else scale = CBUtils::randomFloat(_scale1, _scale2); - - int lifeTime; - if (_lifeTimeZBased) lifeTime = _lifeTime2 - posZ * (_lifeTime2 - _lifeTime1) / 100; - else lifeTime = CBUtils::randomInt(_lifeTime1, _lifeTime2); - - float angle = CBUtils::randomAngle(_angle1, _angle2); - int spriteIndex = CBUtils::randomInt(0, _sprites.getSize() - 1); - - float rotation = CBUtils::randomAngle(_rotation1, _rotation2); - float angVelocity = CBUtils::randomFloat(_angVelocity1, _angVelocity2); - float growthRate = CBUtils::randomFloat(_growthRate1, _growthRate2); - - if (!CBPlatform::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(CBUtils::normalizeAngle(angle - 180))); - matRot.transformVector2(vecVel); - - if (_alphaTimeBased) { - particle->_alpha1 = _alpha1; - particle->_alpha2 = _alpha2; - } else { - int alpha = CBUtils::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 CPartEmitter::update() { - if (!_running) return STATUS_OK; - else return updateInternal(_gameRef->_timer, _gameRef->_timerDelta); -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::updateInternal(uint32 currentTime, uint32 timerDelta) { - int numLive = 0; - - for (int i = 0; i < _particles.getSize(); 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 (int i = 0; i < _particles.getSize(); i++) { - if (_particles[i]->_isDead) { - firstDeadIndex = i; - break; - } - } - - CPartParticle *particle; - if (firstDeadIndex >= 0) particle = _particles[firstDeadIndex]; - else { - particle = new CPartParticle(_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 CPartEmitter::display(CBRegion *region) { - if (_sprites.getSize() <= 1) _gameRef->_renderer->startSpriteBatch(); - - for (int i = 0; i < _particles.getSize(); 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.getSize() <= 1) _gameRef->_renderer->endSpriteBatch(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::start() { - for (int i = 0; i < _particles.getSize(); 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 CPartEmitter::sortParticlesByZ() { - // sort particles by _posY - qsort(_particles.getData(), _particles.getSize(), sizeof(CPartParticle *), CPartEmitter::compareZ); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -int CPartEmitter::compareZ(const void *obj1, const void *obj2) { - CPartParticle *p1 = *(CPartParticle **)obj1; - CPartParticle *p2 = *(CPartParticle **)obj2; - - if (p1->_posZ < p2->_posZ) return -1; - else if (p1->_posZ > p2->_posZ) return 1; - else return 0; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::setBorder(int x, int y, int width, int height) { - CBPlatform::setRect(&_border, x, y, x + width, y + height); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom) { - _borderThicknessLeft = thicknessLeft; - _borderThicknessRight = thicknessRight; - _borderThicknessTop = thicknessTop; - _borderThicknessBottom = thicknessBottom; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -CPartForce *CPartEmitter::addForceByName(const char *name) { - CPartForce *force = NULL; - - for (int i = 0; i < _forces.getSize(); i++) { - if (scumm_stricmp(name, _forces[i]->_name) == 0) { - force = _forces[i]; - break; - } - } - if (!force) { - force = new CPartForce(_gameRef); - if (force) { - force->setName(name); - _forces.add(force); - } - } - return force; -} - - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::addForce(const char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength) { - CPartForce *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(CBUtils::normalizeAngle(angle - 180))); - matRot.transformVector2(force->_direction); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::removeForce(const char *name) { - for (int i = 0; i < _forces.getSize(); i++) { - if (scumm_stricmp(name, _forces[i]->_name) == 0) { - delete _forces[i]; - _forces.removeAt(i); - return STATUS_OK; - } - } - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 (int i = 0; i < _particles.getSize(); i++) { - delete _particles[i]; - } - _particles.removeAll(); - - _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, CPartForce::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, CPartForce::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 CBObject::scCallMethod(script, stack, thisStack, name); -} - -////////////////////////////////////////////////////////////////////////// -CScValue *CPartEmitter::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 (int i = 0; i < _particles.getSize(); 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 CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::scSetProperty(const char *name, CScValue *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()) CBUtils::setString(&_emitEvent, value->getString()); - return STATUS_OK; - } - - else return CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CPartEmitter::scToString() { - return "[particle emitter]"; -} - - - - -////////////////////////////////////////////////////////////////////////// -bool CPartEmitter::persist(CBPersistMgr *persistMgr) { - CBObject::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); - - int numForces; - if (persistMgr->_saving) { - numForces = _forces.getSize(); - persistMgr->transfer(TMEMBER(numForces)); - for (int i = 0; i < _forces.getSize(); i++) { - _forces[i]->persist(persistMgr); - } - } else { - persistMgr->transfer(TMEMBER(numForces)); - for (int i = 0; i < numForces; i++) { - CPartForce *force = new CPartForce(_gameRef); - force->persist(persistMgr); - _forces.add(force); - } - } - - int numParticles; - if (persistMgr->_saving) { - numParticles = _particles.getSize(); - persistMgr->transfer(TMEMBER(numParticles)); - for (int i = 0; i < _particles.getSize(); i++) { - _particles[i]->persist(persistMgr); - } - } else { - persistMgr->transfer(TMEMBER(numParticles)); - for (int i = 0; i < numParticles; i++) { - CPartParticle *particle = new CPartParticle(_gameRef); - particle->persist(persistMgr); - _particles.add(particle); - } - } - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/particles/PartEmitter.h b/engines/wintermute/base/particles/PartEmitter.h deleted file mode 100644 index 5156783653..0000000000 --- a/engines/wintermute/base/particles/PartEmitter.h +++ /dev/null @@ -1,139 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" -#include "engines/wintermute/base/particles/PartForce.h" - -namespace WinterMute { -class CBRegion; -class CPartParticle; -class CPartEmitter : public CBObject { -public: - DECLARE_PERSISTENT(CPartEmitter, CBObject) - - CPartEmitter(CBGame *inGame, CBScriptHolder *Owner); - virtual ~CPartEmitter(void); - - 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 _fadeOutTime; - - int _alpha1; - int _alpha2; - bool _alphaTimeBased; - - bool _useRegion; - - char *_emitEvent; - CBScriptHolder *_owner; - - bool start(); - - bool update(); - bool display() { return display(NULL); } // To avoid shadowing the inherited display-function. - bool display(CBRegion *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 char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength); - bool removeForce(const char *name); - - CBArray _forces; - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); - - -private: - CPartForce *addForceByName(const char *name); - int static compareZ(const void *obj1, const void *obj2); - bool initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta); - bool updateInternal(uint32 currentTime, uint32 timerDelta); - uint32 _lastGenTime; - CBArray _particles; - CBArray _sprites; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/particles/PartForce.cpp b/engines/wintermute/base/particles/PartForce.cpp deleted file mode 100644 index b864c05292..0000000000 --- a/engines/wintermute/base/particles/PartForce.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/persistent.h" -#include "engines/wintermute/base/particles/PartForce.h" -#include "engines/wintermute/base/BPersistMgr.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CPartForce::CPartForce(CBGame *inGame) : CBNamedObject(inGame) { - _pos = Vector2(0.0f, 0.0f); - _direction = Vector2(0.0f, 0.0f); - _type = FORCE_POINT; -} - - -////////////////////////////////////////////////////////////////////////// -CPartForce::~CPartForce(void) { -} - - -////////////////////////////////////////////////////////////////////////// -bool CPartForce::persist(CBPersistMgr *persistMgr) { - persistMgr->transfer(TMEMBER(_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/PartForce.h b/engines/wintermute/base/particles/PartForce.h deleted file mode 100644 index 640c8d7f20..0000000000 --- a/engines/wintermute/base/particles/PartForce.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" -#include "engines/wintermute/base/BNamedObject.h" -#include "engines/wintermute/math/Vector2.h" - -namespace WinterMute { - -class CPartForce : public CBNamedObject { -public: - enum TForceType { - FORCE_POINT, FORCE_GLOBAL - }; - - CPartForce(CBGame *inGame); - virtual ~CPartForce(void); - - Vector2 _pos; - Vector2 _direction; - TForceType _type; - - bool persist(CBPersistMgr *PersistMgr); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/particles/PartParticle.cpp b/engines/wintermute/base/particles/PartParticle.cpp deleted file mode 100644 index 1439231993..0000000000 --- a/engines/wintermute/base/particles/PartParticle.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/particles/PartParticle.h" -#include "engines/wintermute/base/particles/PartEmitter.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" -#include - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CPartParticle::CPartParticle(CBGame *inGame) : CBBase(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; - CBPlatform::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; -} - - -////////////////////////////////////////////////////////////////////////// -CPartParticle::~CPartParticle(void) { - delete _sprite; - _sprite = NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartParticle::setSprite(const char *filename) { - if (_sprite && _sprite->_filename && scumm_stricmp(filename, _sprite->_filename) == 0) { - _sprite->reset(); - return STATUS_OK; - } - - delete _sprite; - _sprite = NULL; - - CSysClassRegistry::getInstance()->_disabled = true; - _sprite = new CBSprite(_gameRef, _gameRef); - if (_sprite && DID_SUCCEED(_sprite->loadFile(filename))) { - CSysClassRegistry::getInstance()->_disabled = false; - return STATUS_OK; - } else { - delete _sprite; - _sprite = NULL; - CSysClassRegistry::getInstance()->_disabled = false; - return STATUS_FAILED; - } - -} - -////////////////////////////////////////////////////////////////////////// -bool CPartParticle::update(CPartEmitter *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 && !CBPlatform::isRectEmpty(&_border)) { - Point32 p; - p.x = (int32)_pos.x; - p.y = (int32)_pos.y; - if (!CBPlatform::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 (int i = 0; i < emitter->_forces.getSize(); i++) { - CPartForce *force = emitter->_forces[i]; - switch (force->_type) { - case CPartForce::FORCE_GLOBAL: - _velocity += force->_direction * elapsedTime; - break; - - case CPartForce::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 = CBUtils::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 CPartParticle::display(CPartEmitter *emitter) { - if (!_sprite) return STATUS_FAILED; - if (_isDead) return STATUS_OK; - - _sprite->GetCurrentFrame(); - return _sprite->display(_pos.x, _pos.y, - NULL, - _scale, _scale, - BYTETORGBA(255, 255, 255, _currentAlpha), - _rotation, - emitter->_blendMode); -} - - -////////////////////////////////////////////////////////////////////////// -bool CPartParticle::fadeIn(uint32 currentTime, int fadeTime) { - _currentAlpha = 0; - _fadeStart = currentTime; - _fadeTime = fadeTime; - _state = PARTICLE_FADEIN; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartParticle::fadeOut(uint32 currentTime, int fadeTime) { - //_currentAlpha = 255; - _fadeStartAlpha = _currentAlpha; - _fadeStart = currentTime; - _fadeTime = fadeTime; - _state = PARTICLE_FADEOUT; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CPartParticle::persist(CBPersistMgr *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->_saving) { - persistMgr->transfer(TMEMBER(_sprite->_filename)); - } else { - char *filename; - persistMgr->transfer(TMEMBER(filename)); - CSysClassRegistry::getInstance()->_disabled = true; - setSprite(filename); - CSysClassRegistry::getInstance()->_disabled = false; - delete[] filename; - filename = NULL; - } - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/particles/PartParticle.h b/engines/wintermute/base/particles/PartParticle.h deleted file mode 100644 index ab5730d3c5..0000000000 --- a/engines/wintermute/base/particles/PartParticle.h +++ /dev/null @@ -1,90 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" -#include "engines/wintermute/math/Rect32.h" -#include "engines/wintermute/math/Vector2.h" - -namespace WinterMute { - -class CPartEmitter; -class CBSprite; -class CBPersistMgr; - -class CPartParticle : public CBBase { -public: - enum TParticleState { - PARTICLE_NORMAL, PARTICLE_FADEIN, PARTICLE_FADEOUT - }; - - CPartParticle(CBGame *inGame); - virtual ~CPartParticle(void); - - float _growthRate; - bool _exponentialGrowth; - - float _rotation; - float _angVelocity; - - int _alpha1; - int _alpha2; - - Rect32 _border; - Vector2 _pos; - float _posZ; - Vector2 _velocity; - float _scale; - CBSprite *_sprite; - uint32 _creationTime; - int _lifeTime; - bool _isDead; - TParticleState _state; - - bool update(CPartEmitter *emitter, uint32 currentTime, uint32 timerDelta); - bool display(CPartEmitter *emitter); - - bool setSprite(const char *filename); - - bool fadeIn(uint32 currentTime, int fadeTime); - bool fadeOut(uint32 currentTime, int fadeTime); - - bool persist(CBPersistMgr *PersistMgr); -private: - uint32 _fadeStart; - int _fadeTime; - int _currentAlpha; - int _fadeStartAlpha; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp new file mode 100644 index 0000000000..11ebafd329 --- /dev/null +++ b/engines/wintermute/base/particles/part_emitter.cpp @@ -0,0 +1,1199 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CPartEmitter, false) + +////////////////////////////////////////////////////////////////////////// +CPartEmitter::CPartEmitter(CBGame *inGame, CBScriptHolder *Owner) : CBObject(inGame) { + _width = _height = 0; + + CBPlatform::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; +} + + +////////////////////////////////////////////////////////////////////////// +CPartEmitter::~CPartEmitter(void) { + for (int i = 0; i < _particles.getSize(); i++) { + delete _particles[i]; + } + _particles.removeAll(); + + for (int i = 0; i < _forces.getSize(); i++) { + delete _forces[i]; + } + _forces.removeAll(); + + + for (int i = 0; i < _sprites.getSize(); i++) { + delete [] _sprites[i]; + } + _sprites.removeAll(); + + delete[] _emitEvent; + _emitEvent = NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::addSprite(const char *filename) { + if (!filename) return STATUS_FAILED; + + // do we already have the file? + for (int i = 0; i < _sprites.getSize(); i++) { + if (scumm_stricmp(filename, _sprites[i]) == 0) return STATUS_OK; + } + + // check if file exists + Common::SeekableReadStream *File = _gameRef->_fileManager->openFile(filename); + if (!File) { + _gameRef->LOG(0, "Sprite '%s' not found", filename); + return STATUS_FAILED; + } else _gameRef->_fileManager->closeFile(File); + + char *Str = new char[strlen(filename) + 1]; + strcpy(Str, filename); + _sprites.add(Str); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::removeSprite(const char *filename) { + for (int i = 0; i < _sprites.getSize(); i++) { + if (scumm_stricmp(filename, _sprites[i]) == 0) { + delete [] _sprites[i]; + _sprites.removeAt(i); + return STATUS_OK; + } + } + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta) { + if (!particle) return STATUS_FAILED; + if (_sprites.getSize() == 0) return STATUS_FAILED; + + int posX = CBUtils::randomInt(_posX, _posX + _width); + int posY = CBUtils::randomInt(_posY, _posY + _height); + float posZ = CBUtils::randomFloat(0.0f, 100.0f); + + float velocity; + if (_velocityZBased) velocity = _velocity1 + posZ * (_velocity2 - _velocity1) / 100; + else velocity = CBUtils::randomFloat(_velocity1, _velocity2); + + float scale; + if (_scaleZBased) scale = _scale1 + posZ * (_scale2 - _scale1) / 100; + else scale = CBUtils::randomFloat(_scale1, _scale2); + + int lifeTime; + if (_lifeTimeZBased) lifeTime = _lifeTime2 - posZ * (_lifeTime2 - _lifeTime1) / 100; + else lifeTime = CBUtils::randomInt(_lifeTime1, _lifeTime2); + + float angle = CBUtils::randomAngle(_angle1, _angle2); + int spriteIndex = CBUtils::randomInt(0, _sprites.getSize() - 1); + + float rotation = CBUtils::randomAngle(_rotation1, _rotation2); + float angVelocity = CBUtils::randomFloat(_angVelocity1, _angVelocity2); + float growthRate = CBUtils::randomFloat(_growthRate1, _growthRate2); + + if (!CBPlatform::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(CBUtils::normalizeAngle(angle - 180))); + matRot.transformVector2(vecVel); + + if (_alphaTimeBased) { + particle->_alpha1 = _alpha1; + particle->_alpha2 = _alpha2; + } else { + int alpha = CBUtils::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 CPartEmitter::update() { + if (!_running) return STATUS_OK; + else return updateInternal(_gameRef->_timer, _gameRef->_timerDelta); +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::updateInternal(uint32 currentTime, uint32 timerDelta) { + int numLive = 0; + + for (int i = 0; i < _particles.getSize(); 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 (int i = 0; i < _particles.getSize(); i++) { + if (_particles[i]->_isDead) { + firstDeadIndex = i; + break; + } + } + + CPartParticle *particle; + if (firstDeadIndex >= 0) particle = _particles[firstDeadIndex]; + else { + particle = new CPartParticle(_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 CPartEmitter::display(CBRegion *region) { + if (_sprites.getSize() <= 1) _gameRef->_renderer->startSpriteBatch(); + + for (int i = 0; i < _particles.getSize(); 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.getSize() <= 1) _gameRef->_renderer->endSpriteBatch(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::start() { + for (int i = 0; i < _particles.getSize(); 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 CPartEmitter::sortParticlesByZ() { + // sort particles by _posY + qsort(_particles.getData(), _particles.getSize(), sizeof(CPartParticle *), CPartEmitter::compareZ); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +int CPartEmitter::compareZ(const void *obj1, const void *obj2) { + CPartParticle *p1 = *(CPartParticle **)obj1; + CPartParticle *p2 = *(CPartParticle **)obj2; + + if (p1->_posZ < p2->_posZ) return -1; + else if (p1->_posZ > p2->_posZ) return 1; + else return 0; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::setBorder(int x, int y, int width, int height) { + CBPlatform::setRect(&_border, x, y, x + width, y + height); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom) { + _borderThicknessLeft = thicknessLeft; + _borderThicknessRight = thicknessRight; + _borderThicknessTop = thicknessTop; + _borderThicknessBottom = thicknessBottom; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +CPartForce *CPartEmitter::addForceByName(const char *name) { + CPartForce *force = NULL; + + for (int i = 0; i < _forces.getSize(); i++) { + if (scumm_stricmp(name, _forces[i]->_name) == 0) { + force = _forces[i]; + break; + } + } + if (!force) { + force = new CPartForce(_gameRef); + if (force) { + force->setName(name); + _forces.add(force); + } + } + return force; +} + + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::addForce(const char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength) { + CPartForce *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(CBUtils::normalizeAngle(angle - 180))); + matRot.transformVector2(force->_direction); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::removeForce(const char *name) { + for (int i = 0; i < _forces.getSize(); i++) { + if (scumm_stricmp(name, _forces[i]->_name) == 0) { + delete _forces[i]; + _forces.removeAt(i); + return STATUS_OK; + } + } + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 (int i = 0; i < _particles.getSize(); i++) { + delete _particles[i]; + } + _particles.removeAll(); + + _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, CPartForce::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, CPartForce::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 CBObject::scCallMethod(script, stack, thisStack, name); +} + +////////////////////////////////////////////////////////////////////////// +CScValue *CPartEmitter::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 (int i = 0; i < _particles.getSize(); 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 CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::scSetProperty(const char *name, CScValue *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()) CBUtils::setString(&_emitEvent, value->getString()); + return STATUS_OK; + } + + else return CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CPartEmitter::scToString() { + return "[particle emitter]"; +} + + + + +////////////////////////////////////////////////////////////////////////// +bool CPartEmitter::persist(CBPersistMgr *persistMgr) { + CBObject::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); + + int numForces; + if (persistMgr->_saving) { + numForces = _forces.getSize(); + persistMgr->transfer(TMEMBER(numForces)); + for (int i = 0; i < _forces.getSize(); i++) { + _forces[i]->persist(persistMgr); + } + } else { + persistMgr->transfer(TMEMBER(numForces)); + for (int i = 0; i < numForces; i++) { + CPartForce *force = new CPartForce(_gameRef); + force->persist(persistMgr); + _forces.add(force); + } + } + + int numParticles; + if (persistMgr->_saving) { + numParticles = _particles.getSize(); + persistMgr->transfer(TMEMBER(numParticles)); + for (int i = 0; i < _particles.getSize(); i++) { + _particles[i]->persist(persistMgr); + } + } else { + persistMgr->transfer(TMEMBER(numParticles)); + for (int i = 0; i < numParticles; i++) { + CPartParticle *particle = new CPartParticle(_gameRef); + particle->persist(persistMgr); + _particles.add(particle); + } + } + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/particles/part_emitter.h b/engines/wintermute/base/particles/part_emitter.h new file mode 100644 index 0000000000..cff0a1ec83 --- /dev/null +++ b/engines/wintermute/base/particles/part_emitter.h @@ -0,0 +1,139 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CBRegion; +class CPartParticle; +class CPartEmitter : public CBObject { +public: + DECLARE_PERSISTENT(CPartEmitter, CBObject) + + CPartEmitter(CBGame *inGame, CBScriptHolder *Owner); + virtual ~CPartEmitter(void); + + 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 _fadeOutTime; + + int _alpha1; + int _alpha2; + bool _alphaTimeBased; + + bool _useRegion; + + char *_emitEvent; + CBScriptHolder *_owner; + + bool start(); + + bool update(); + bool display() { return display(NULL); } // To avoid shadowing the inherited display-function. + bool display(CBRegion *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 char *name, CPartForce::TForceType type, int posX, int posY, float angle, float strength); + bool removeForce(const char *name); + + CBArray _forces; + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); + + +private: + CPartForce *addForceByName(const char *name); + int static compareZ(const void *obj1, const void *obj2); + bool initParticle(CPartParticle *particle, uint32 currentTime, uint32 timerDelta); + bool updateInternal(uint32 currentTime, uint32 timerDelta); + uint32 _lastGenTime; + CBArray _particles; + CBArray _sprites; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/particles/part_force.cpp b/engines/wintermute/base/particles/part_force.cpp new file mode 100644 index 0000000000..2f330c21b0 --- /dev/null +++ b/engines/wintermute/base/particles/part_force.cpp @@ -0,0 +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 + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/particles/part_force.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CPartForce::CPartForce(CBGame *inGame) : CBNamedObject(inGame) { + _pos = Vector2(0.0f, 0.0f); + _direction = Vector2(0.0f, 0.0f); + _type = FORCE_POINT; +} + + +////////////////////////////////////////////////////////////////////////// +CPartForce::~CPartForce(void) { +} + + +////////////////////////////////////////////////////////////////////////// +bool CPartForce::persist(CBPersistMgr *persistMgr) { + persistMgr->transfer(TMEMBER(_name)); + persistMgr->transfer(TMEMBER(_pos)); + persistMgr->transfer(TMEMBER(_direction)); + persistMgr->transfer(TMEMBER_INT(_type)); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/particles/part_force.h b/engines/wintermute/base/particles/part_force.h new file mode 100644 index 0000000000..f0a6d66c43 --- /dev/null +++ b/engines/wintermute/base/particles/part_force.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_PARTFORCE_H +#define WINTERMUTE_PARTFORCE_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/base/base_named_object.h" +#include "engines/wintermute/math/vector2.h" + +namespace WinterMute { + +class CPartForce : public CBNamedObject { +public: + enum TForceType { + FORCE_POINT, FORCE_GLOBAL + }; + + CPartForce(CBGame *inGame); + virtual ~CPartForce(void); + + Vector2 _pos; + Vector2 _direction; + TForceType _type; + + bool persist(CBPersistMgr *PersistMgr); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/particles/part_particle.cpp b/engines/wintermute/base/particles/part_particle.cpp new file mode 100644 index 0000000000..931f7558c7 --- /dev/null +++ b/engines/wintermute/base/particles/part_particle.cpp @@ -0,0 +1,257 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/particles/part_particle.h" +#include "engines/wintermute/base/particles/part_emitter.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" +#include + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CPartParticle::CPartParticle(CBGame *inGame) : CBBase(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; + CBPlatform::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; +} + + +////////////////////////////////////////////////////////////////////////// +CPartParticle::~CPartParticle(void) { + delete _sprite; + _sprite = NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartParticle::setSprite(const char *filename) { + if (_sprite && _sprite->_filename && scumm_stricmp(filename, _sprite->_filename) == 0) { + _sprite->reset(); + return STATUS_OK; + } + + delete _sprite; + _sprite = NULL; + + CSysClassRegistry::getInstance()->_disabled = true; + _sprite = new CBSprite(_gameRef, _gameRef); + if (_sprite && DID_SUCCEED(_sprite->loadFile(filename))) { + CSysClassRegistry::getInstance()->_disabled = false; + return STATUS_OK; + } else { + delete _sprite; + _sprite = NULL; + CSysClassRegistry::getInstance()->_disabled = false; + return STATUS_FAILED; + } + +} + +////////////////////////////////////////////////////////////////////////// +bool CPartParticle::update(CPartEmitter *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 && !CBPlatform::isRectEmpty(&_border)) { + Point32 p; + p.x = (int32)_pos.x; + p.y = (int32)_pos.y; + if (!CBPlatform::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 (int i = 0; i < emitter->_forces.getSize(); i++) { + CPartForce *force = emitter->_forces[i]; + switch (force->_type) { + case CPartForce::FORCE_GLOBAL: + _velocity += force->_direction * elapsedTime; + break; + + case CPartForce::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 = CBUtils::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 CPartParticle::display(CPartEmitter *emitter) { + if (!_sprite) return STATUS_FAILED; + if (_isDead) return STATUS_OK; + + _sprite->GetCurrentFrame(); + return _sprite->display(_pos.x, _pos.y, + NULL, + _scale, _scale, + BYTETORGBA(255, 255, 255, _currentAlpha), + _rotation, + emitter->_blendMode); +} + + +////////////////////////////////////////////////////////////////////////// +bool CPartParticle::fadeIn(uint32 currentTime, int fadeTime) { + _currentAlpha = 0; + _fadeStart = currentTime; + _fadeTime = fadeTime; + _state = PARTICLE_FADEIN; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartParticle::fadeOut(uint32 currentTime, int fadeTime) { + //_currentAlpha = 255; + _fadeStartAlpha = _currentAlpha; + _fadeStart = currentTime; + _fadeTime = fadeTime; + _state = PARTICLE_FADEOUT; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CPartParticle::persist(CBPersistMgr *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->_saving) { + persistMgr->transfer(TMEMBER(_sprite->_filename)); + } else { + char *filename; + persistMgr->transfer(TMEMBER(filename)); + CSysClassRegistry::getInstance()->_disabled = true; + setSprite(filename); + CSysClassRegistry::getInstance()->_disabled = false; + delete[] filename; + filename = NULL; + } + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/particles/part_particle.h b/engines/wintermute/base/particles/part_particle.h new file mode 100644 index 0000000000..0b256d44ec --- /dev/null +++ b/engines/wintermute/base/particles/part_particle.h @@ -0,0 +1,90 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_PARTPARTICLE_H +#define WINTERMUTE_PARTPARTICLE_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/math/rect32.h" +#include "engines/wintermute/math/vector2.h" + +namespace WinterMute { + +class CPartEmitter; +class CBSprite; +class CBPersistMgr; + +class CPartParticle : public CBBase { +public: + enum TParticleState { + PARTICLE_NORMAL, PARTICLE_FADEIN, PARTICLE_FADEOUT + }; + + CPartParticle(CBGame *inGame); + virtual ~CPartParticle(void); + + float _growthRate; + bool _exponentialGrowth; + + float _rotation; + float _angVelocity; + + int _alpha1; + int _alpha2; + + Rect32 _border; + Vector2 _pos; + float _posZ; + Vector2 _velocity; + float _scale; + CBSprite *_sprite; + uint32 _creationTime; + int _lifeTime; + bool _isDead; + TParticleState _state; + + bool update(CPartEmitter *emitter, uint32 currentTime, uint32 timerDelta); + bool display(CPartEmitter *emitter); + + bool setSprite(const char *filename); + + bool fadeIn(uint32 currentTime, int fadeTime); + bool fadeOut(uint32 currentTime, int fadeTime); + + bool persist(CBPersistMgr *PersistMgr); +private: + uint32 _fadeStart; + int _fadeTime; + int _currentAlpha; + int _fadeStartAlpha; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/SXArray.cpp b/engines/wintermute/base/scriptables/SXArray.cpp deleted file mode 100644 index 425118a3e7..0000000000 --- a/engines/wintermute/base/scriptables/SXArray.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/system/SysInstance.h" -#include "engines/wintermute/base/scriptables/SXArray.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CSXArray, false) - -CBScriptable *makeSXArray(CBGame *inGame, CScStack *stack) { - return new CSXArray(inGame, stack); -} - -////////////////////////////////////////////////////////////////////////// -CSXArray::CSXArray(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { - _length = 0; - _values = new CScValue(_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()); - } - } -} - -////////////////////////////////////////////////////////////////////////// -CSXArray::CSXArray(CBGame *inGame): CBScriptable(inGame) { - _length = 0; - _values = new CScValue(_gameRef); -} - - -////////////////////////////////////////////////////////////////////////// -CSXArray::~CSXArray() { - delete _values; - _values = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -const char *CSXArray::scToString() { - static char dummy[32768]; // TODO: Get rid of static. - strcpy(dummy, ""); - char propName[20]; - for (int i = 0; i < _length; i++) { - sprintf(propName, "%d", i); - CScValue *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, ","); - } - return dummy; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXArray::scCallMethod(CScScript *script, CScStack *stack, CScStack *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; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CSXArray::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 CSXArray::scSetProperty(const char *name, CScValue *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 CSXArray::persist(CBPersistMgr *persistMgr) { - CBScriptable::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_length)); - persistMgr->transfer(TMEMBER(_values)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXArray::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 CSXArray::push(CScValue *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/SXArray.h b/engines/wintermute/base/scriptables/SXArray.h deleted file mode 100644 index 0f46bd546e..0000000000 --- a/engines/wintermute/base/scriptables/SXArray.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BScriptable.h" - -namespace WinterMute { - -class CSXArray : public CBScriptable { -public: - bool push(CScValue *Val); - bool validNumber(const char *origStr, char *outStr); - DECLARE_PERSISTENT(CSXArray, CBScriptable) - CSXArray(CBGame *inGame, CScStack *stack); - CSXArray(CBGame *inGame); - virtual ~CSXArray(); - CScValue *scGetProperty(const char *name); - bool scSetProperty(const char *name, CScValue *value); - bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - const char *scToString(); - int _length; - CScValue *_values; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/SXDate.cpp b/engines/wintermute/base/scriptables/SXDate.cpp deleted file mode 100644 index cd705cc9d4..0000000000 --- a/engines/wintermute/base/scriptables/SXDate.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/SXDate.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CSXDate, false) - -CBScriptable *makeSXDate(CBGame *inGame, CScStack *stack) { - return new CSXDate(inGame, stack); -} - -////////////////////////////////////////////////////////////////////////// -CSXDate::CSXDate(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { - stack->correctParams(6); - - memset(&_tm, 0, sizeof(_tm)); - - CScValue *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); - } -} - - -////////////////////////////////////////////////////////////////////////// -CSXDate::~CSXDate() { - -} - -////////////////////////////////////////////////////////////////////////// -const char *CSXDate::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(); -#if 0 - return asctime(&_tm); -#endif -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXDate::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); - warning("GetWeekday returns a wrong value on purpose"); - stack->pushInt(_tm.tm_mday % 7); - 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; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CSXDate::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("date"); - return _scValue; - } - - else return _scValue; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXDate::scSetProperty(const char *name, CScValue *value) { - /* - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if(strcmp(name, "Name")==0){ - setName(value->getString()); - return STATUS_OK; - } - - else*/ return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXDate::persist(CBPersistMgr *persistMgr) { - - CBScriptable::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 CSXDate::scCompare(CBScriptable *Value) { - TimeDate time1 = _tm; - TimeDate time2 = ((CSXDate *)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/SXDate.h b/engines/wintermute/base/scriptables/SXDate.h deleted file mode 100644 index df0641983f..0000000000 --- a/engines/wintermute/base/scriptables/SXDate.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BScriptable.h" - -namespace WinterMute { - -class CSXDate : public CBScriptable { -public: - int scCompare(CBScriptable *Value); - DECLARE_PERSISTENT(CSXDate, CBScriptable) - CSXDate(CBGame *inGame, CScStack *Stack); - virtual ~CSXDate(); - CScValue *scGetProperty(const char *name); - bool scSetProperty(const char *name, CScValue *value); - bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - const char *scToString(); - char *_string; - TimeDate _tm; -private: - Common::String _strRep; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/SXFile.cpp b/engines/wintermute/base/scriptables/SXFile.cpp deleted file mode 100644 index 1924a42d72..0000000000 --- a/engines/wintermute/base/scriptables/SXFile.cpp +++ /dev/null @@ -1,779 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/SysClassRegistry.h" -#include "engines/wintermute/system/SysClass.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/file/BFile.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/SXFile.h" - -// Note: This code is completely untested, as I have yet to find a game that uses SXFile. - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CSXFile, false) - -CBScriptable *makeSXFile(CBGame *inGame, CScStack *stack) { - return new CSXFile(inGame, stack); -} - -////////////////////////////////////////////////////////////////////////// -CSXFile::CSXFile(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { - stack->correctParams(1); - CScValue *Val = stack->pop(); - - _filename = NULL; - if (!Val->isNULL()) CBUtils::setString(&_filename, Val->getString()); - - _readFile = NULL; - _writeFile = NULL; - - _mode = 0; - _textMode = false; -} - - -////////////////////////////////////////////////////////////////////////// -CSXFile::~CSXFile() { - cleanup(); -} - -////////////////////////////////////////////////////////////////////////// -void CSXFile::cleanup() { - delete[] _filename; - _filename = NULL; - close(); -} - - -////////////////////////////////////////////////////////////////////////// -void CSXFile::close() { - if (_readFile) { - _gameRef->_fileManager->closeFile(_readFile); - _readFile = NULL; - } - if (_writeFile) { - _writeFile->finalize(); - delete _writeFile; - _writeFile = NULL; - } - _mode = 0; - _textMode = false; -} - -////////////////////////////////////////////////////////////////////////// -const char *CSXFile::scToString() { - if (_filename) return _filename; - else return "[file object]"; -} - -#define FILE_BUFFER_SIZE 32768 -////////////////////////////////////////////////////////////////////////// -bool CSXFile::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetFilename - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetFilename") == 0) { - stack->correctParams(1); - const char *filename = stack->pop()->getString(); - cleanup(); - CBUtils::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 = _gameRef->_fileManager->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(); - stack->pushBool(CBPlatform::deleteFile(_filename) != 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(); - stack->pushBool(CBPlatform::copyFile(_filename, Dest, !Overwrite) != 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 CBScriptable::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CSXFile::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 CBScriptable::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXFile::scSetProperty(const char *name, CScValue *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 CBScriptable::scSetProperty(name, value); -} - -////////////////////////////////////////////////////////////////////////// -uint32 CSXFile::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 CSXFile::setPos(uint32 pos, int whence) { - if (_mode == 1 && _readFile) - return _readFile->seek(pos, whence); - else if ((_mode == 2 || _mode == 3) && _writeFile) { - error("CSXFile - seeking in WriteFile not supported"); - return false; -// return fseek((FILE *)_writeFile, pos, (int)origin) == 0; - } - else return false; -} - -////////////////////////////////////////////////////////////////////////// -uint32 CSXFile::getLength() { - if (_mode == 1 && _readFile) - return _readFile->size(); - else if ((_mode == 2 || _mode == 3) && _writeFile) { - error("CSXFile - 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 CSXFile::persist(CBPersistMgr *persistMgr) { - - CBScriptable::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_filename)); - persistMgr->transfer(TMEMBER(_mode)); - persistMgr->transfer(TMEMBER(_textMode)); - - uint32 pos = 0; - if (persistMgr->_saving) { - 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 = _gameRef->_fileManager->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 *CSXFile::openForWrite(const Common::String &filename, bool binary) { - error("SXFile::openForWrite - WriteFiles not supported"); -} - -// Should replace fopen(..., "ab+") and fopen(..., "a+") -Common::WriteStream *CSXFile::openForAppend(const Common::String &filename, bool binary) { - error("SXFile::openForAppend - WriteFiles not supported"); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/SXFile.h b/engines/wintermute/base/scriptables/SXFile.h deleted file mode 100644 index 709d1f4378..0000000000 --- a/engines/wintermute/base/scriptables/SXFile.h +++ /dev/null @@ -1,66 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 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/BScriptable.h" -#include "common/stream.h" - -namespace WinterMute { - -class CBFile; - -class CSXFile : public CBScriptable { -public: - DECLARE_PERSISTENT(CSXFile, CBScriptable) - CScValue *scGetProperty(const char *name); - bool scSetProperty(const char *name, CScValue *value); - bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - const char *scToString(); - CSXFile(CBGame *inGame, CScStack *Stack); - virtual ~CSXFile(); -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/SXMath.cpp b/engines/wintermute/base/scriptables/SXMath.cpp deleted file mode 100644 index fb2838ee94..0000000000 --- a/engines/wintermute/base/scriptables/SXMath.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/SXMath.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/persistent.h" -#include "common/math.h" -#include - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - - -IMPLEMENT_PERSISTENT(CSXMath, true) - -CBScriptable *makeSXMath(CBGame *inGame) { - return new CSXMath(inGame); -} - -////////////////////////////////////////////////////////////////////////// -CSXMath::CSXMath(CBGame *inGame): CBScriptable(inGame) { - -} - - -////////////////////////////////////////////////////////////////////////// -CSXMath::~CSXMath() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXMath::scCallMethod(CScScript *script, CScStack *stack, CScStack *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; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CSXMath::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 CSXMath::degreeToRadian(double value) { - return value * (M_PI / 180.0f); -} - - -////////////////////////////////////////////////////////////////////////// -double CSXMath::radianToDegree(double value) { - return value * (180.0f / M_PI); -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXMath::persist(CBPersistMgr *persistMgr) { - - CBScriptable::persist(persistMgr); - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/SXMath.h b/engines/wintermute/base/scriptables/SXMath.h deleted file mode 100644 index 4389de611f..0000000000 --- a/engines/wintermute/base/scriptables/SXMath.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BScriptable.h" - -namespace WinterMute { - -class CSXMath : public CBScriptable { -public: - DECLARE_PERSISTENT(CSXMath, CBScriptable) - CSXMath(CBGame *inGame); - virtual ~CSXMath(); - virtual CScValue *scGetProperty(const char *name); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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/SXMemBuffer.cpp b/engines/wintermute/base/scriptables/SXMemBuffer.cpp deleted file mode 100644 index 9ac98ab11d..0000000000 --- a/engines/wintermute/base/scriptables/SXMemBuffer.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BScriptable.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/SXMemBuffer.h" -#include "common/file.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CSXMemBuffer, false) - -CBScriptable *makeSXMemBuffer(CBGame *inGame, CScStack *stack) { - return new CSXMemBuffer(inGame, stack); -} - -////////////////////////////////////////////////////////////////////////// -CSXMemBuffer::CSXMemBuffer(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { - stack->correctParams(1); - _buffer = NULL; - _size = 0; - - int NewSize = stack->pop()->getInt(); - resize(MAX(0, NewSize)); -} - -////////////////////////////////////////////////////////////////////////// -CSXMemBuffer::CSXMemBuffer(CBGame *inGame, void *Buffer): CBScriptable(inGame) { - _size = 0; - _buffer = Buffer; -} - - -////////////////////////////////////////////////////////////////////////// -CSXMemBuffer::~CSXMemBuffer() { - cleanup(); -} - -////////////////////////////////////////////////////////////////////////// -void *CSXMemBuffer::scToMemBuffer() { - return _buffer; -} - -////////////////////////////////////////////////////////////////////////// -void CSXMemBuffer::cleanup() { - if (_size) free(_buffer); - _buffer = NULL; - _size = 0; -} - -////////////////////////////////////////////////////////////////////////// -bool CSXMemBuffer::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 CSXMemBuffer::checkBounds(CScScript *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 *CSXMemBuffer::scToString() { - return "[membuffer object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXMemBuffer::scCallMethod(CScScript *script, CScStack *stack, CScStack *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]; - strncpy(str, (const char *)_buffer + start, length); - str[length] = '\0'; - 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); - CSXMemBuffer *buf = new CSXMemBuffer(_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(); - /* CScValue *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; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CSXMemBuffer::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 CBScriptable::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXMemBuffer::scSetProperty(const char *name, CScValue *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 CBScriptable::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXMemBuffer::persist(CBPersistMgr *persistMgr) { - - CBScriptable::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_size)); - - if (persistMgr->_saving) { - 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 CSXMemBuffer::scCompare(CBScriptable *val) { - if (_buffer == val->scToMemBuffer()) return 0; - else return 1; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/SXMemBuffer.h b/engines/wintermute/base/scriptables/SXMemBuffer.h deleted file mode 100644 index 09831bf464..0000000000 --- a/engines/wintermute/base/scriptables/SXMemBuffer.h +++ /dev/null @@ -1,59 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BScriptable.h" - -namespace WinterMute { - -class CSXMemBuffer : public CBScriptable { -public: - virtual int scCompare(CBScriptable *Val); - DECLARE_PERSISTENT(CSXMemBuffer, CBScriptable) - CScValue *scGetProperty(const char *name); - bool scSetProperty(const char *name, CScValue *value); - bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - const char *scToString(); - CSXMemBuffer(CBGame *inGame, CScStack *stack); - CSXMemBuffer(CBGame *inGame, void *buffer); - virtual ~CSXMemBuffer(); - virtual void *scToMemBuffer(); - int _size; -private: - bool resize(int newSize); - void *_buffer; - void cleanup(); - bool checkBounds(CScScript *script, int start, int length); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/SXString.cpp b/engines/wintermute/base/scriptables/SXString.cpp deleted file mode 100644 index ed3d243cb0..0000000000 --- a/engines/wintermute/base/scriptables/SXString.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/base/scriptables/SXString.h" -#include "engines/wintermute/base/scriptables/SXArray.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "common/tokenizer.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CSXString, false) - -CBScriptable *makeSXString(CBGame *inGame, CScStack *stack) { - return new CSXString(inGame, stack); -} - -////////////////////////////////////////////////////////////////////////// -CSXString::CSXString(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { - _string = NULL; - _capacity = 0; - - stack->correctParams(1); - CScValue *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(""); -} - - -////////////////////////////////////////////////////////////////////////// -CSXString::~CSXString() { - if (_string) delete [] _string; -} - - -////////////////////////////////////////////////////////////////////////// -void CSXString::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 *CSXString::scToString() { - if (_string) return _string; - else return "[null string]"; -} - - -////////////////////////////////////////////////////////////////////////// -void CSXString::scSetString(const char *val) { - setStringVal(val); -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXString::scCallMethod(CScScript *script, CScStack *stack, CScStack *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) CBUtils::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(); - - CScValue *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); - CScValue *val = stack->pop(); - char separators[MAX_PATH_LENGTH] = ","; - if (!val->isNULL()) strcpy(separators, val->getString()); - - CSXArray *array = new CSXArray(_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 CScValue(_gameRef, StringUtil::wideToUtf8(part).c_str()); - else - val = new CScValue(_gameRef, StringUtil::wideToAnsi(part).c_str()); - - array->push(val); - delete val; - val = NULL; - } - - stack->pushNative(array, false); - return STATUS_OK; - } - - else return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CSXString::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 CSXString::scSetProperty(const char *name, CScValue *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 CSXString::persist(CBPersistMgr *persistMgr) { - - CBScriptable::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_capacity)); - - if (persistMgr->_saving) { - 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 CSXString::scCompare(CBScriptable *val) { - return strcmp(_string, ((CSXString *)val)->_string); -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/SXString.h b/engines/wintermute/base/scriptables/SXString.h deleted file mode 100644 index 348595ad29..0000000000 --- a/engines/wintermute/base/scriptables/SXString.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BScriptable.h" - -namespace WinterMute { - -class CSXString : public CBScriptable { -public: - virtual int scCompare(CBScriptable *Val); - DECLARE_PERSISTENT(CSXString, CBScriptable) - CScValue *scGetProperty(const char *name); - bool scSetProperty(const char *name, CScValue *value); - bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - void scSetString(const char *val); - const char *scToString(); - void setStringVal(const char *val); - - CSXString(CBGame *inGame, CScStack *Stack); - virtual ~CSXString(); - -private: - char *_string; - int _capacity; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/ScEngine.cpp b/engines/wintermute/base/scriptables/ScEngine.cpp deleted file mode 100644 index db79a7d0e9..0000000000 --- a/engines/wintermute/base/scriptables/ScEngine.cpp +++ /dev/null @@ -1,712 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/scriptables/ScEngine.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/SXMath.h" -#include "engines/wintermute/base/BRegistry.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BFileManager.h" - - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CScEngine, true) - -#define COMPILER_DLL "dcscomp.dll" -////////////////////////////////////////////////////////////////////////// -CScEngine::CScEngine(CBGame *inGame): CBBase(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 CScValue(_gameRef); - - - // register 'Game' as global variable - if (!_globals->propExists("Game")) { - CScValue val(_gameRef); - val.setNative(_gameRef, true); - _globals->setProp("Game", &val); - } - - // register 'Math' as global variable - if (!_globals->propExists("Math")) { - CScValue 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(); -} - - -////////////////////////////////////////////////////////////////////////// -CScEngine::~CScEngine() { - _gameRef->LOG(0, "Shutting down scripting engine"); - saveBreakpoints(); - - disableProfiling(); - - cleanup(); - - for (int i = 0; i < _breakpoints.getSize(); i++) { - delete _breakpoints[i]; - _breakpoints[i] = NULL; - } - _breakpoints.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::cleanup() { - for (int i = 0; i < _scripts.getSize(); i++) { - if (!_scripts[i]->_thread && _scripts[i]->_owner) _scripts[i]->_owner->removeScript(_scripts[i]); - delete _scripts[i]; - _scripts.removeAt(i); - i--; - } - - _scripts.removeAll(); - - delete _globals; - _globals = NULL; - - emptyScriptCache(); - - _currentScript = NULL; // ref only - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -byte *CScEngine::loadFile(void *data, char *filename, uint32 *size) { - CBGame *gameRef = (CBGame *)data; - return gameRef->_fileManager->readWholeFile(filename, size); -} - - -////////////////////////////////////////////////////////////////////////// -void CScEngine::closeFile(void *data, byte *buffer) { - delete [] buffer; -} - - -////////////////////////////////////////////////////////////////////////// -void CScEngine::parseElement(void *data, int line, int type, void *elementData) { -} - - -////////////////////////////////////////////////////////////////////////// -CScScript *CScEngine::runScript(const char *filename, CBScriptHolder *owner) { - byte *compBuffer; - uint32 compSize; - - // get script from cache - compBuffer = getCompiledScript(filename, &compSize); - if (!compBuffer) return NULL; - - // add new script - CScScript *script = new CScScript(_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 - CScValue val(_gameRef); - if (owner)val.setNative(owner, true); - else val.setNULL(); - - script->_globals->setProp("self", &val); - script->_globals->setProp("this", &val); - - _scripts.add(script); - _gameRef->getDebugMgr()->onScriptInit(script); - - return script; - } -} - - -////////////////////////////////////////////////////////////////////////// -byte *CScEngine::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 = CBPlatform::getTime(); - *outSize = _cachedScripts[i]->_size; - return _cachedScripts[i]->_buffer; - } - } - } - - // nope, load it - byte *compBuffer; - uint32 compSize; - - uint32 size; - - byte *buffer = _gameRef->_fileManager->readWholeFile(filename, &size); - if (!buffer) { - _gameRef->LOG(0, "CScEngine::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, "CScEngine::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 = CBPlatform::getTime(); - 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 CScEngine::tick() { - if (_scripts.getSize() == 0) - return STATUS_OK; - - - // resolve waiting scripts - for (int i = 0; i < _scripts.getSize(); i++) { - - switch (_scripts[i]->_state) { - case SCRIPT_WAITING: { - /* - bool obj_found=false; - for(int j=0; j<_gameRef->_regObjects.getSize(); 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 <= CBPlatform::getTime()) _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: - //warning("CScEngine::Tick - Unhandled enum"); - break; - } // switch - } // for each script - - - // execute scripts - for (int i = 0; i < _scripts.getSize(); i++) { - - // skip paused scripts - if (_scripts[i]->_state == SCRIPT_PAUSED) continue; - - // time sliced script - if (_scripts[i]->_timeSlice > 0) { - uint32 StartTime = CBPlatform::getTime(); - while (_scripts[i]->_state == SCRIPT_RUNNING && CBPlatform::getTime() - StartTime < _scripts[i]->_timeSlice) { - _currentScript = _scripts[i]; - _scripts[i]->executeInstruction(); - } - if (_isProfiling && _scripts[i]->_filename) addScriptTime(_scripts[i]->_filename, CBPlatform::getTime() - StartTime); - } - - // normal script - else { - uint32 startTime = 0; - bool isProfiling = _isProfiling; - if (isProfiling) startTime = CBPlatform::getTime(); - - while (_scripts[i]->_state == SCRIPT_RUNNING) { - _currentScript = _scripts[i]; - _scripts[i]->executeInstruction(); - } - if (isProfiling && _scripts[i]->_filename) addScriptTime(_scripts[i]->_filename, CBPlatform::getTime() - startTime); - } - _currentScript = NULL; - } - - removeFinishedScripts(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::tickUnbreakable() { - // execute unbreakable scripts - for (int i = 0; i < _scripts.getSize(); 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 CScEngine::removeFinishedScripts() { - // remove finished scripts - for (int i = 0; i < _scripts.getSize(); 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]); - _gameRef->getDebugMgr()->onScriptShutdown(_scripts[i]); - delete _scripts[i]; - _scripts.removeAt(i); - i--; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int CScEngine::getNumScripts(int *running, int *waiting, int *persistent) { - int numRunning = 0, numWaiting = 0, numPersistent = 0, numTotal = 0; - - for (int i = 0; i < _scripts.getSize(); 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("CScEngine::GetNumScripts - unhandled enum"); - break; - } - numTotal++; - } - if (running) *running = numRunning; - if (waiting) *waiting = numWaiting; - if (persistent) *persistent = numPersistent; - - return numTotal; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::emptyScriptCache() { - for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { - if (_cachedScripts[i]) { - delete _cachedScripts[i]; - _cachedScripts[i] = NULL; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::resetObject(CBObject *Object) { - // terminate all scripts waiting for this object - for (int i = 0; i < _scripts.getSize(); 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 CScEngine::resetScript(CScScript *script) { - // terminate all scripts waiting for this script - for (int i = 0; i < _scripts.getSize(); i++) { - if (_scripts[i]->_state == SCRIPT_WAITING_SCRIPT && _scripts[i]->_waitScript == script) { - _scripts[i]->finish(); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::persist(CBPersistMgr *persistMgr) { - if (!persistMgr->_saving) cleanup(); - - persistMgr->transfer(TMEMBER(_gameRef)); - persistMgr->transfer(TMEMBER(_currentScript)); - persistMgr->transfer(TMEMBER(_globals)); - _scripts.persist(persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CScEngine::editorCleanup() { - for (int i = 0; i < _scripts.getSize(); i++) { - if (_scripts[i]->_owner == NULL && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) { - delete _scripts[i]; - _scripts.removeAt(i); - i--; - } - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::pauseAll() { - for (int i = 0; i < _scripts.getSize(); i++) { - if (_scripts[i] != _currentScript) _scripts[i]->pause(); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::resumeAll() { - for (int i = 0; i < _scripts.getSize(); i++) - _scripts[i]->resume(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::isValidScript(CScScript *script) { - for (int i = 0; i < _scripts.getSize(); i++) { - if (_scripts[i] == script) return true; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::clearGlobals(bool includingNatives) { - _globals->CleanProps(includingNatives); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::dbgSendScripts(IWmeDebugClient *client) { - // send global variables - _globals->dbgSendVariables(client, WME_DBGVAR_GLOBAL, NULL, 0); - - // process normal scripts first - for (int i = 0; i < _scripts.getSize(); i++) { - if (_scripts[i]->_thread || _scripts[i]->_methodThread) continue; - _scripts[i]->dbgSendScript(client); - } - - // and threads later - for (int i = 0; i < _scripts.getSize(); i++) { - if (_scripts[i]->_thread || _scripts[i]->_methodThread) - _scripts[i]->dbgSendScript(client); - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::addBreakpoint(const char *scriptFilename, int line) { - if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; - - CScBreakpoint *bp = NULL; - for (int i = 0; i < _breakpoints.getSize(); i++) { - if (scumm_stricmp(_breakpoints[i]->_filename.c_str(), scriptFilename) == 0) { - bp = _breakpoints[i]; - break; - } - } - if (bp == NULL) { - bp = new CScBreakpoint(scriptFilename); - _breakpoints.add(bp); - } - - for (int i = 0; i < bp->_lines.getSize(); i++) { - if (bp->_lines[i] == line) return STATUS_OK; - } - bp->_lines.add(line); - - // refresh changes - refreshScriptBreakpoints(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::removeBreakpoint(const char *scriptFilename, int line) { - if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; - - for (int i = 0; i < _breakpoints.getSize(); i++) { - if (scumm_stricmp(_breakpoints[i]->_filename.c_str(), scriptFilename) == 0) { - for (int j = 0; j < _breakpoints[i]->_lines.getSize(); j++) { - if (_breakpoints[i]->_lines[j] == line) { - _breakpoints[i]->_lines.removeAt(j); - if (_breakpoints[i]->_lines.getSize() == 0) { - delete _breakpoints[i]; - _breakpoints.removeAt(i); - } - // refresh changes - refreshScriptBreakpoints(); - - return STATUS_OK; - } - } - break; - } - } - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::refreshScriptBreakpoints() { - if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; - - for (int i = 0; i < _scripts.getSize(); i++) { - refreshScriptBreakpoints(_scripts[i]); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::refreshScriptBreakpoints(CScScript *script) { - if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; - - if (!script || !script->_filename) return STATUS_FAILED; - - for (int i = 0; i < _breakpoints.getSize(); i++) { - if (scumm_stricmp(_breakpoints[i]->_filename.c_str(), script->_filename) == 0) { - script->_breakpoints.copy(_breakpoints[i]->_lines); - return STATUS_OK; - } - } - if (script->_breakpoints.getSize() > 0) script->_breakpoints.removeAll(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::saveBreakpoints() { - if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; - - - char text[512]; - char key[100]; - - int count = 0; - for (int i = 0; i < _breakpoints.getSize(); i++) { - for (int j = 0; j < _breakpoints[i]->_lines.getSize(); j++) { - count++; - sprintf(key, "Breakpoint%d", count); - sprintf(text, "%s:%d", _breakpoints[i]->_filename.c_str(), _breakpoints[i]->_lines[j]); - - _gameRef->_registry->writeString("Debug", key, text); - } - } - _gameRef->_registry->writeInt("Debug", "NumBreakpoints", count); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScEngine::loadBreakpoints() { - if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; - - char key[100]; - - int count = _gameRef->_registry->readInt("Debug", "NumBreakpoints", 0); - for (int i = 1; i <= count; i++) { - /* uint32 BufSize = 512; */ - sprintf(key, "Breakpoint%d", i); - AnsiString breakpoint = _gameRef->_registry->readString("Debug", key, ""); - - char *path = CBUtils::strEntry(0, breakpoint.c_str(), ':'); - char *line = CBUtils::strEntry(1, breakpoint.c_str(), ':'); - - if (path != NULL && line != NULL) addBreakpoint(path, atoi(line)); - delete[] path; - delete[] line; - path = NULL; - line = NULL; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CScEngine::addScriptTime(const char *filename, uint32 time) { - if (!_isProfiling) return; - - AnsiString fileName = filename; - fileName.toLowercase(); - _scriptTimes[fileName] += time; -} - - -////////////////////////////////////////////////////////////////////////// -void CScEngine::enableProfiling() { - if (_isProfiling) return; - - // destroy old data, if any - _scriptTimes.clear(); - - _profilingStartTime = CBPlatform::getTime(); - _isProfiling = true; -} - - -////////////////////////////////////////////////////////////////////////// -void CScEngine::disableProfiling() { - if (!_isProfiling) return; - - dumpStats(); - _isProfiling = false; -} - - -////////////////////////////////////////////////////////////////////////// -void CScEngine::dumpStats() { - error("DumpStats not ported to ScummVM yet"); - /* uint32 totalTime = CBPlatform::getTime() - _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/ScEngine.h b/engines/wintermute/base/scriptables/ScEngine.h deleted file mode 100644 index 0322319b3d..0000000000 --- a/engines/wintermute/base/scriptables/ScEngine.h +++ /dev/null @@ -1,147 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" -#include "engines/wintermute/wme_debugger.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -#define MAX_CACHED_SCRIPTS 20 -class CScScript; -class CScValue; -class CBObject; -class CBScriptHolder; -class CScEngine : public CBBase { -public: - class CScCachedScript { - public: - CScCachedScript(const char *filename, byte *buffer, uint32 size) { - _timestamp = CBPlatform::getTime(); - _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.removeAll(); - } - - Common::String _filename; - CBArray _lines; - }; - - - - -public: - bool dbgSendScripts(IWmeDebugClient *client); - - CBArray _breakpoints; - bool addBreakpoint(const char *scriptFilename, int line); - bool removeBreakpoint(const char *scriptFilename, int line); - bool refreshScriptBreakpoints(); - bool refreshScriptBreakpoints(CScScript *script); - bool saveBreakpoints(); - bool loadBreakpoints(); - - bool clearGlobals(bool includingNatives = false); - bool tickUnbreakable(); - bool removeFinishedScripts(); - bool isValidScript(CScScript *script); - - CScScript *_currentScript; - bool resumeAll(); - bool pauseAll(); - void editorCleanup(); - bool resetObject(CBObject *Object); - bool resetScript(CScScript *script); - bool emptyScriptCache(); - byte *getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache = false); - DECLARE_PERSISTENT(CScEngine, CBBase) - bool cleanup(); - int getNumScripts(int *running = NULL, int *waiting = NULL, int *persistent = NULL); - bool tick(); - CScValue *_globals; - CScScript *runScript(const char *filename, CBScriptHolder *owner = NULL); - static const bool _compilerAvailable = false; - - CScEngine(CBGame *inGame); - virtual ~CScEngine(); - 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); - - CBArray _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/ScScript.cpp b/engines/wintermute/base/scriptables/ScScript.cpp deleted file mode 100644 index 0b5b3c24bf..0000000000 --- a/engines/wintermute/base/scriptables/ScScript.cpp +++ /dev/null @@ -1,1461 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "common/memstream.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CScScript, false) - -////////////////////////////////////////////////////////////////////////// -CScScript::CScScript(CBGame *inGame, CScEngine *Engine): CBBase(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; -} - - -////////////////////////////////////////////////////////////////////////// -CScScript::~CScScript() { - cleanup(); -} - -void CScScript::readHeader() { - uint32 oldPos = _scriptStream->pos(); - _scriptStream->seek(0); - _header.magic = _scriptStream->readUint32LE(); - _header.version = _scriptStream->readUint32LE(); - _header.code_start = _scriptStream->readUint32LE(); - _header.func_table = _scriptStream->readUint32LE(); - _header.symbol_table = _scriptStream->readUint32LE(); - _header.event_table = _scriptStream->readUint32LE(); - _header.externals_table = _scriptStream->readUint32LE(); - _header.method_table = _scriptStream->readUint32LE(); - _scriptStream->seek(oldPos); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::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 CScStack(_gameRef); - _callStack = new CScStack(_gameRef); - _thisStack = new CScStack(_gameRef); - _stack = new CScStack(_gameRef); - - _operand = new CScValue(_gameRef); - _reg1 = new CScValue(_gameRef); - - - // skip to the beginning - _iP = _header.code_start; - _scriptStream->seek(_iP); - _currentLine = 0; - - // init breakpoints - _engine->refreshScriptBreakpoints(this); - - - // ready to rumble... - _state = SCRIPT_RUNNING; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::initTables() { - uint32 OrigIP = _iP; - - readHeader(); - // load symbol table - _iP = _header.symbol_table; - - _numSymbols = getDWORD(); - _symbols = new char*[_numSymbols]; - for (uint32 i = 0; i < _numSymbols; i++) { - uint32 index = getDWORD(); - _symbols[index] = getString(); - } - - // load functions table - _iP = _header.func_table; - - _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.event_table; - - _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.externals_table; - - _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.method_table; - - _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 CScScript::create(const char *filename, byte *buffer, uint32 size, CBScriptHolder *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 CScValue(_gameRef); - - _owner = owner; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::createThread(CScScript *original, uint32 initIP, const char *eventName) { - cleanup(); - - _thread = true; - _methodThread = false; - _threadEvent = new char[strlen(eventName) + 1]; - if (_threadEvent) strcpy(_threadEvent, eventName); - - // 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 CScScript::createMethodThread(CScScript *original, const char *methodName) { - uint32 ip = original->getMethodPos(methodName); - if (ip == 0) return STATUS_FAILED; - - cleanup(); - - _thread = true; - _methodThread = true; - _threadEvent = new char[strlen(methodName) + 1]; - if (_threadEvent) strcpy(_threadEvent, methodName); - - // 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 CScScript::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 CScScript::getDWORD() { - _scriptStream->seek((int32)_iP); - uint32 ret = _scriptStream->readUint32LE(); - _iP += sizeof(uint32); -// assert(oldRet == ret); - return ret; -} - -////////////////////////////////////////////////////////////////////////// -double CScScript::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 *CScScript::getString() { - char *ret = (char *)(_buffer + _iP); - while (*(char *)(_buffer + _iP) != '\0') _iP++; - _iP++; // string terminator - _scriptStream->seek(_iP); - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::executeInstruction() { - bool ret = STATUS_OK; - - uint32 dw; - const char *str = NULL; - - //CScValue* op = new CScValue(_gameRef); - _operand->cleanup(); - - CScValue *op1; - CScValue *op2; - - uint32 inst = getDWORD(); - switch (inst) { - - case II_DEF_VAR: - _operand->setNULL(); - dw = getDWORD(); - if (_scopeStack->_sP < 0) { - _globals->setProp(_symbols[dw], _operand); - if (_gameRef->getDebugMgr()->_enabled) - _gameRef->getDebugMgr()->onVariableInit(WME_DBGVAR_SCRIPT, this, NULL, _globals->getProp(_symbols[dw]), _symbols[dw]); - } else { - _scopeStack->getTop()->setProp(_symbols[dw], _operand); - if (_gameRef->getDebugMgr()->_enabled) - _gameRef->getDebugMgr()->onVariableInit(WME_DBGVAR_SCOPE, this, _scopeStack->getTop(), _scopeStack->getTop()->getProp(_symbols[dw]), _symbols[dw]); - } - - 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); - - if (_gameRef->getDebugMgr()->_enabled) - _gameRef->getDebugMgr()->onVariableInit(WME_DBGVAR_GLOBAL, this, NULL, _engine->_globals->getProp(_symbols[dw]), _symbols[dw]); - } - break; - } - - case II_RET: - if (_scopeStack->_sP >= 0 && _callStack->_sP >= 0) { - _gameRef->getDebugMgr()->onScriptShutdownScope(this, _scopeStack->getTop()); - - _scopeStack->pop(); - _iP = (uint32)_callStack->pop()->getInt(); - - if (_scopeStack->_sP < 0) _gameRef->getDebugMgr()->onScriptChangeScope(this, NULL); - else _gameRef->getDebugMgr()->onScriptChangeScope(this, _scopeStack->getTop()); - } 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); - - CScValue *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; - } - /* - CScValue* 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); - - if (_scopeStack->_sP < 0) _gameRef->getDebugMgr()->onScriptChangeScope(this, NULL); - else _gameRef->getDebugMgr()->onScriptChangeScope(this, _scopeStack->getTop()); - - 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: { - CScValue *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: { - CScValue *var = getVar(_symbols[getDWORD()]); - _operand->setReference(var); - _stack->push(_operand); - break; - } - - case II_POP_VAR: { - char *VarName = _symbols[getDWORD()]; - CScValue *var = getVar(VarName); - if (var) { - CScValue *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); - } - } - - if (_gameRef->getDebugMgr()->_enabled) - _gameRef->getDebugMgr()->onVariableChangeValue(var, 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(); - CScValue *val = _stack->pop()->getProp(str); - if (val) _stack->push(val); - else _stack->pushNULL(); - - break; - } - - case II_POP_BY_EXP: { - str = _stack->pop()->getString(); - CScValue *var = _stack->pop(); - CScValue *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); - - if (_gameRef->getDebugMgr()->_enabled) - _gameRef->getDebugMgr()->onVariableChangeValue(var, NULL); - - 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; - CScValue *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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::compareStrict(op1, op2) != 0); - _stack->push(_operand); - break; - - case II_DBG_LINE: { - int newLine = getDWORD(); - if (newLine != _currentLine) { - _currentLine = newLine; - if (_gameRef->getDebugMgr()->_enabled) { - _gameRef->getDebugMgr()->onScriptChangeLine(this, _currentLine); - for (int i = 0; i < _breakpoints.getSize(); i++) { - if (_breakpoints[i] == _currentLine) { - _gameRef->getDebugMgr()->onScriptHitBreakpoint(this); - sleep(0); - break; - } - } - if (_tracingMode) { - _gameRef->getDebugMgr()->onScriptHitBreakpoint(this); - sleep(0); - break; - } - } - } - 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 CScScript::getFuncPos(const char *name) { - for (uint32 i = 0; i < _numFunctions; i++) { - if (strcmp(name, _functions[i].name) == 0) - return _functions[i].pos; - } - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CScScript::getMethodPos(const char *name) { - for (uint32 i = 0; i < _numMethods; i++) { - if (strcmp(name, _methods[i].name) == 0) - return _methods[i].pos; - } - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CScScript::getVar(char *name) { - CScValue *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); - CScValue *val = new CScValue(_gameRef); - CScValue *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 CScScript::waitFor(CBObject *object) { - if (_unbreakable) { - runtimeError("Script cannot be interrupted."); - return STATUS_OK; - } - - _state = SCRIPT_WAITING; - _waitObject = object; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::waitForExclusive(CBObject *object) { - _engine->resetObject(object); - return waitFor(object); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::sleep(uint32 duration) { - if (_unbreakable) { - runtimeError("Script cannot be interrupted."); - return STATUS_OK; - } - - _state = SCRIPT_SLEEPING; - if (_gameRef->_state == GAME_FROZEN) { - _waitTime = CBPlatform::getTime() + duration; - _waitFrozen = true; - } else { - _waitTime = _gameRef->_timer + duration; - _waitFrozen = false; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::finish(bool includingThreads) { - if (_state != SCRIPT_FINISHED && includingThreads) { - _state = SCRIPT_FINISHED; - finishThreads(); - } else _state = SCRIPT_FINISHED; - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::run() { - _state = SCRIPT_RUNNING; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////// -void CScScript::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 CScScript::persist(CBPersistMgr *persistMgr) { - - persistMgr->transfer(TMEMBER(_gameRef)); - - // buffer - if (persistMgr->_saving) { - 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->_saving) _tracingMode = false; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CScScript *CScScript::invokeEventHandler(const char *eventName, bool unbreakable) { - //if(_state!=SCRIPT_PERSISTENT) return NULL; - - uint32 pos = getEventPos(eventName); - if (!pos) return NULL; - - CScScript *thread = new CScScript(_gameRef, _engine); - if (thread) { - bool ret = thread->createThread(this, pos, eventName); - if (DID_SUCCEED(ret)) { - thread->_unbreakable = unbreakable; - _engine->_scripts.add(thread); - _gameRef->getDebugMgr()->onScriptEventThreadInit(thread, this, eventName); - return thread; - } else { - delete thread; - return NULL; - } - } else return NULL; - -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CScScript::getEventPos(const char *name) { - for (int i = _numEvents - 1; i >= 0; i--) { - if (scumm_stricmp(name, _events[i].name) == 0) return _events[i].pos; - } - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::canHandleEvent(const char *eventName) { - return getEventPos(eventName) != 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::canHandleMethod(const char *methodName) { - return getMethodPos(methodName) != 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::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 CScScript::resume() { - if (_state != SCRIPT_PAUSED) return STATUS_OK; - - _state = _origState; - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CScScript::TExternalFunction *CScScript::getExternal(char *name) { - for (uint32 i = 0; i < _numExternals; i++) { - if (strcmp(name, _externals[i].name) == 0) - return &_externals[i]; - } - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::externalCall(CScStack *stack, CScStack *thisStack, CScScript::TExternalFunction *function) { - - _gameRef->LOG(0, "External functions are not supported on this platform."); - stack->correctParams(0); - stack->pushNULL(); - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::copyParameters(CScStack *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 CScScript::finishThreads() { - for (int i = 0; i < _engine->_scripts.getSize(); i++) { - CScScript *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 CScScript::dbgGetLine() { - return _currentLine; -} - -////////////////////////////////////////////////////////////////////////// -const char *CScScript::dbgGetFilename() { - return _filename; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScScript::dbgSendScript(IWmeDebugClient *client) { - if (_methodThread) client->onScriptMethodThreadInit(this, _parentScript, _threadEvent); - else if (_thread) client->onScriptEventThreadInit(this, _parentScript, _threadEvent); - else client->onScriptInit(this); - - return dbgSendVariables(client); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CScScript::dbgSendVariables(IWmeDebugClient *client) { - // send script globals - _globals->dbgSendVariables(client, WME_DBGVAR_SCRIPT, this, 0); - - // send scope variables - if (_scopeStack->_sP >= 0) { - for (int i = 0; i <= _scopeStack->_sP; i++) { - // CScValue *Scope = _scopeStack->GetAt(i); - //Scope->DbgSendVariables(Client, WME_DBGVAR_SCOPE, this, (unsigned int)Scope); - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -TScriptState CScScript::dbgGetState() { - return _state; -} - -////////////////////////////////////////////////////////////////////////// -int CScScript::dbgGetNumBreakpoints() { - return _breakpoints.getSize(); -} - -////////////////////////////////////////////////////////////////////////// -int CScScript::dbgGetBreakpoint(int index) { - if (index >= 0 && index < _breakpoints.getSize()) return _breakpoints[index]; - else return -1; -} - -////////////////////////////////////////////////////////////////////////// -bool CScScript::dbgSetTracingMode(bool isTracing) { - _tracingMode = isTracing; - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CScScript::dbgGetTracingMode() { - return _tracingMode; -} - - -////////////////////////////////////////////////////////////////////////// -void CScScript::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/ScScript.h b/engines/wintermute/base/scriptables/ScScript.h deleted file mode 100644 index c031f8186f..0000000000 --- a/engines/wintermute/base/scriptables/ScScript.h +++ /dev/null @@ -1,183 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" -#include "engines/wintermute/dcscript.h" // Added by ClassView -#include "engines/wintermute/coll_templ.h" - -#include "engines/wintermute/wme_debugger.h" - -namespace WinterMute { -class CBScriptHolder; -class CBObject; -class CScEngine; -class CScStack; -class CScScript : public CBBase, public IWmeDebugScript { -public: - bool dbgSendScript(IWmeDebugClient *client); - bool dbgSendVariables(IWmeDebugClient *client); - - CBArray _breakpoints; - bool _tracingMode; - - CScScript *_parentScript; - bool _unbreakable; - bool finishThreads(); - bool copyParameters(CScStack *stack); - - void afterLoad(); - - CScValue *_operand; - CScValue *_reg1; - bool _freezable; - bool resume(); - bool pause(); - bool canHandleEvent(const char *eventName); - bool canHandleMethod(const char *methodName); - bool createThread(CScScript *original, uint32 initIP, const char *eventName); - bool createMethodThread(CScScript *original, const char *methodName); - CScScript *invokeEventHandler(const char *eventName, bool unbreakable = false); - uint32 _timeSlice; - DECLARE_PERSISTENT(CScScript, CBBase) - void runtimeError(const char *fmt, ...); - bool run(); - bool finish(bool includingThreads = false); - bool sleep(uint32 duration); - bool waitForExclusive(CBObject *object); - bool waitFor(CBObject *object); - uint32 _waitTime; - bool _waitFrozen; - CBObject *_waitObject; - CScScript *_waitScript; - TScriptState _state; - TScriptState _origState; - CScValue *getVar(char *name); - uint32 getFuncPos(const char *name); - uint32 getEventPos(const char *name); - uint32 getMethodPos(const char *name); - typedef struct { - uint32 magic; - uint32 version; - uint32 code_start; - uint32 func_table; - uint32 symbol_table; - uint32 event_table; - uint32 externals_table; - uint32 method_table; - } 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; - - - CScStack *_callStack; - CScStack *_thisStack; - CScStack *_scopeStack; - CScStack *_stack; - CScValue *_globals; - CScEngine *_engine; - int _currentLine; - bool executeInstruction(); - char *getString(); - uint32 getDWORD(); - double getFloat(); - void cleanup(); - bool create(const char *filename, byte *buffer, uint32 size, CBScriptHolder *owner); - uint32 _iP; -private: - void readHeader(); - uint32 _bufferSize; - byte *_buffer; -public: - Common::SeekableReadStream *_scriptStream; - CScScript(CBGame *inGame, CScEngine *Engine); - virtual ~CScScript(); - char *_filename; - char **_symbols; - uint32 _numSymbols; - TFunctionPos *_functions; - TMethodPos *_methods; - TEventPos *_events; - uint32 _numExternals; - TExternalFunction *_externals; - uint32 _numFunctions; - uint32 _numMethods; - uint32 _numEvents; - bool _thread; - bool _methodThread; - char *_threadEvent; - CBScriptHolder *_owner; - CScScript::TExternalFunction *getExternal(char *name); - bool externalCall(CScStack *stack, CScStack *thisStack, CScScript::TExternalFunction *function); -private: - bool initScript(); - bool initTables(); - - -// IWmeDebugScript interface implementation -public: - virtual int dbgGetLine(); - virtual const char *dbgGetFilename(); - virtual TScriptState dbgGetState(); - virtual int dbgGetNumBreakpoints(); - virtual int dbgGetBreakpoint(int Index); - - virtual bool dbgSetTracingMode(bool IsTracing); - virtual bool dbgGetTracingMode(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/ScStack.cpp b/engines/wintermute/base/scriptables/ScStack.cpp deleted file mode 100644 index 252cd21dda..0000000000 --- a/engines/wintermute/base/scriptables/ScStack.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/BGame.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CScStack, false) - -////////////////////////////////////////////////////////////////////////// -CScStack::CScStack(CBGame *inGame): CBBase(inGame) { - _sP = -1; -} - - -////////////////////////////////////////////////////////////////////////// -CScStack::~CScStack() { - -#if _DEBUG - //_gameRef->LOG(0, "STAT: Stack size: %d, SP=%d", _values.getSize(), _sP); -#endif - - for (int i = 0; i < _values.getSize(); i++) { - delete _values[i]; - } - _values.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CScStack::pop() { - if (_sP < 0) { - _gameRef->LOG(0, "Fatal: Stack underflow"); - return NULL; - } - - return _values[_sP--]; -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::push(CScValue *val) { - _sP++; - - if (_sP < _values.getSize()) { - _values[_sP]->cleanup(); - _values[_sP]->copy(val); - } else { - CScValue *copyVal = new CScValue(_gameRef); - copyVal->copy(val); - _values.add(copyVal); - } -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CScStack::getPushValue() { - _sP++; - - if (_sP >= _values.getSize()) { - CScValue *val = new CScValue(_gameRef); - _values.add(val); - } - _values[_sP]->cleanup(); - return _values[_sP]; -} - - - -////////////////////////////////////////////////////////////////////////// -CScValue *CScStack::getTop() { - if (_sP < 0 || _sP >= _values.getSize()) return NULL; - else return _values[_sP]; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CScStack::getAt(int index) { - index = _sP - index; - if (index < 0 || index >= _values.getSize()) return NULL; - else return _values[index]; -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::correctParams(uint32 expectedParams) { - uint32 nuParams = (uint32)pop()->getInt(); - - if (expectedParams < nuParams) { // too many params - while (expectedParams < nuParams) { - //Pop(); - delete _values[_sP - expectedParams]; - _values.removeAt(_sP - expectedParams); - nuParams--; - _sP--; - } - } else if (expectedParams > nuParams) { // need more params - while (expectedParams > nuParams) { - //Push(null_val); - CScValue *nullVal = new CScValue(_gameRef); - nullVal->setNULL(); - _values.insertAt(_sP - nuParams + 1, nullVal); - nuParams++; - _sP++; - - if (_values.getSize() > _sP + 1) { - delete _values[_values.getSize() - 1]; - _values.removeAt(_values.getSize() - 1); - } - } - } -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::pushNULL() { - /* - CScValue* val = new CScValue(_gameRef); - val->setNULL(); - Push(val); - delete val; - */ - getPushValue()->setNULL(); -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::pushInt(int val) { - /* - CScValue* val = new CScValue(_gameRef); - val->setInt(Val); - Push(val); - delete val; - */ - getPushValue()->setInt(val); -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::pushFloat(double val) { - /* - CScValue* val = new CScValue(_gameRef); - val->setFloat(Val); - Push(val); - delete val; - */ - getPushValue()->setFloat(val); -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::pushBool(bool val) { - /* - CScValue* val = new CScValue(_gameRef); - val->setBool(Val); - Push(val); - delete val; - */ - getPushValue()->setBool(val); -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::pushString(const char *val) { - /* - CScValue* val = new CScValue(_gameRef); - val->setString(Val); - Push(val); - delete val; - */ - getPushValue()->setString(val); -} - - -////////////////////////////////////////////////////////////////////////// -void CScStack::pushNative(CBScriptable *val, bool persistent) { - /* - CScValue* val = new CScValue(_gameRef); - val->setNative(Val, Persistent); - Push(val); - delete val; - */ - - getPushValue()->setNative(val, persistent); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScStack::persist(CBPersistMgr *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/ScStack.h b/engines/wintermute/base/scriptables/ScStack.h deleted file mode 100644 index 22dae63060..0000000000 --- a/engines/wintermute/base/scriptables/ScStack.h +++ /dev/null @@ -1,66 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" -#include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/persistent.h" - -namespace WinterMute { - -class CScValue; -class CBScriptable; - -class CScStack : public CBBase { -public: - CScValue *getAt(int Index); - CScValue *getPushValue(); - DECLARE_PERSISTENT(CScStack, CBBase) - void pushNative(CBScriptable *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); - CScValue *getTop(); - void push(CScValue *val); - CScValue *pop(); - CScStack(CBGame *inGame); - virtual ~CScStack(); - CBArray _values; - int _sP; - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/ScValue.cpp b/engines/wintermute/base/scriptables/ScValue.cpp deleted file mode 100644 index f38a12fc7a..0000000000 --- a/engines/wintermute/base/scriptables/ScValue.cpp +++ /dev/null @@ -1,1054 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BDynBuffer.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/base/BScriptable.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CScValue, false) - -////////////////////////////////////////////////////////////////////////// -CScValue::CScValue(CBGame *inGame): CBBase(inGame) { - _type = VAL_NULL; - - _valBool = false; - _valInt = 0; - _valFloat = 0.0f; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; - _persistent = false; - _isConstVar = false; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue::CScValue(CBGame *inGame, bool val): CBBase(inGame) { - _type = VAL_BOOL; - _valBool = val; - - _valInt = 0; - _valFloat = 0.0f; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; - _persistent = false; - _isConstVar = false; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue::CScValue(CBGame *inGame, int val): CBBase(inGame) { - _type = VAL_INT; - _valInt = val; - - _valFloat = 0.0f; - _valBool = false; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; - _persistent = false; - _isConstVar = false; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue::CScValue(CBGame *inGame, double val): CBBase(inGame) { - _type = VAL_FLOAT; - _valFloat = val; - - _valInt = 0; - _valBool = false; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; - _persistent = false; - _isConstVar = false; -} - - -////////////////////////////////////////////////////////////////////////// -CScValue::CScValue(CBGame *inGame, const char *val): CBBase(inGame) { - _type = VAL_STRING; - _valString = NULL; - setStringVal(val); - - _valBool = false; - _valInt = 0; - _valFloat = 0.0f; - _valNative = NULL; - _valRef = NULL; - _persistent = false; - _isConstVar = false; -} - - -////////////////////////////////////////////////////////////////////////// -void CScValue::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; -} - - - -////////////////////////////////////////////////////////////////////////// -CScValue::~CScValue() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CScValue::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 0 // TODO: Remove FreeType-dependency - if (_gameRef->_textEncoding == TEXT_ANSI) { -#else - if (true) { -#endif - _gameRef->_scValue->setInt(strlen(_valString)); - } else { - WideString wstr = StringUtil::utf8ToWide(_valString); - _gameRef->_scValue->setInt(wstr.size()); - } - - return _gameRef->_scValue; - } - - CScValue *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 CScValue::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 CScValue::setProp(const char *name, CScValue *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)) { - CScValue *newVal = NULL; - - _valIter = _valObject.find(name); - if (_valIter != _valObject.end()) { - newVal = _valIter->_value; - } - if (!newVal) - newVal = new CScValue(_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; - } - CScValue* val = new CScValue(_gameRef); - val->Copy(Val, CopyWhole); - val->_isConstVar = SetAsConst; - _valObject[Name] = val; - - if(_type!=VAL_NATIVE) _type = VAL_OBJECT; - */ - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::propExists(const char *name) { - if (_type == VAL_VARIABLE_REF) - return _valRef->propExists(name); - _valIter = _valObject.find(name); - - return (_valIter != _valObject.end()); -} - - -////////////////////////////////////////////////////////////////////////// -void CScValue::deleteProps() { - _valIter = _valObject.begin(); - while (_valIter != _valObject.end()) { - delete(CScValue *)_valIter->_value; - _valIter++; - } - _valObject.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -void CScValue::CleanProps(bool includingNatives) { - _valIter = _valObject.begin(); - while (_valIter != _valObject.end()) { - if (!_valIter->_value->_isConstVar && (!_valIter->_value->isNative() || includingNatives)) _valIter->_value->setNULL(); - _valIter++; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::isNULL() { - if (_type == VAL_VARIABLE_REF) - return _valRef->isNULL(); - - return (_type == VAL_NULL); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::isNative() { - if (_type == VAL_VARIABLE_REF) - return _valRef->isNative(); - - return (_type == VAL_NATIVE); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::isString() { - if (_type == VAL_VARIABLE_REF) - return _valRef->isString(); - - return (_type == VAL_STRING); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::isFloat() { - if (_type == VAL_VARIABLE_REF) - return _valRef->isFloat(); - - return (_type == VAL_FLOAT); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::isInt() { - if (_type == VAL_VARIABLE_REF) - return _valRef->isInt(); - - return (_type == VAL_INT); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::isBool() { - if (_type == VAL_VARIABLE_REF) - return _valRef->isBool(); - - return (_type == VAL_BOOL); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::isObject() { - if (_type == VAL_VARIABLE_REF) - return _valRef->isObject(); - - return (_type == VAL_OBJECT); -} - - -////////////////////////////////////////////////////////////////////////// -TValType CScValue::getTypeTolerant() { - if (_type == VAL_VARIABLE_REF) - return _valRef->getType(); - - return _type; -} - - -////////////////////////////////////////////////////////////////////////// -void CScValue::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 CScValue::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 CScValue::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 CScValue::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 CScValue::setString(const Common::String &val) { - setString(val.c_str()); -} - -////////////////////////////////////////////////////////////////////////// -void CScValue::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 CScValue::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 CScValue::setNative(CBScriptable *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 CScValue::setObject() { - if (_type == VAL_VARIABLE_REF) { - _valRef->setObject(); - return; - } - - deleteProps(); - _type = VAL_OBJECT; -} - - -////////////////////////////////////////////////////////////////////////// -void CScValue::setReference(CScValue *val) { - _valRef = val; - _type = VAL_VARIABLE_REF; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::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 CScValue::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 CScValue::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 *CScValue::getMemBuffer() { - if (_type == VAL_VARIABLE_REF) - return _valRef->getMemBuffer(); - - if (_type == VAL_NATIVE) - return _valNative->scToMemBuffer(); - else return (void *)NULL; -} - - -////////////////////////////////////////////////////////////////////////// -const char *CScValue::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; -} - - -////////////////////////////////////////////////////////////////////////// -CBScriptable *CScValue::getNative() { - if (_type == VAL_VARIABLE_REF) - return _valRef->getNative(); - - if (_type == VAL_NATIVE) return _valNative; - else return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -TValType CScValue::getType() { - return _type; -} - - -////////////////////////////////////////////////////////////////////////// -void CScValue::copy(CScValue *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 CScValue(_gameRef); - _valObject[orig->_valIter->_key]->copy(orig->_valIter->_value); - orig->_valIter++; - } - } else _valObject.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -void CScValue::setValue(CScValue *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("CScValue::setValue - unhandled enum"); - break; - } - } - // otherwise just copy everything - else copy(val); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::persist(CBPersistMgr *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->_saving) { - 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 { - CScValue *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 CScValue::saveAsText(CBDynBuffer *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 CScValue::compare(CScValue *val1, CScValue *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 CScValue::compareStrict(CScValue *val1, CScValue *val2) { - if (val1->getTypeTolerant() != val2->getTypeTolerant()) return -1; - else return CScValue::compare(val1, val2); -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgSendVariables(IWmeDebugClient *client, EWmeDebuggerVariableType type, CScScript *script, unsigned int scopeID) { - _valIter = _valObject.begin(); - while (_valIter != _valObject.end()) { - client->onVariableInit(type, script, scopeID, _valIter->_value, _valIter->_key.c_str()); - _valIter++; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::setProperty(const char *propName, int value) { - CScValue *val = new CScValue(_gameRef, value); - bool ret = DID_SUCCEED(setProp(propName, val)); - delete val; - return ret; -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::setProperty(const char *propName, const char *value) { - CScValue *val = new CScValue(_gameRef, value); - bool ret = DID_SUCCEED(setProp(propName, val)); - delete val; - return ret; -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::setProperty(const char *propName, double value) { - CScValue *val = new CScValue(_gameRef, value); - bool ret = DID_SUCCEED(setProp(propName, val)); - delete val; - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::setProperty(const char *propName, bool value) { - CScValue *val = new CScValue(_gameRef, value); - bool ret = DID_SUCCEED(setProp(propName, val)); - delete val; - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool CScValue::setProperty(const char *propName) { - CScValue *val = new CScValue(_gameRef); - bool ret = DID_SUCCEED(setProp(propName, val)); - delete val; - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -// IWmeDebugProp -////////////////////////////////////////////////////////////////////////// -EWmeDebuggerPropType CScValue::dbgGetType() { - switch (getType()) { - case VAL_NULL: - return WME_DBGPROP_NULL; - case VAL_STRING: - return WME_DBGPROP_STRING; - case VAL_INT: - return WME_DBGPROP_INT; - case VAL_BOOL: - return WME_DBGPROP_BOOL; - case VAL_FLOAT: - return WME_DBGPROP_FLOAT; - case VAL_OBJECT: - return WME_DBGPROP_OBJECT; - case VAL_NATIVE: - return WME_DBGPROP_NATIVE; - default: - return WME_DBGPROP_UNKNOWN; - } -} - -////////////////////////////////////////////////////////////////////////// -int CScValue::dbgGetValInt() { - return getInt(); -} - -////////////////////////////////////////////////////////////////////////// -double CScValue::dbgGetValFloat() { - return getFloat(); -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgGetValBool() { - return getBool(); -} - -////////////////////////////////////////////////////////////////////////// -const char *CScValue::dbgGetValString() { - return getString(); -} - -////////////////////////////////////////////////////////////////////////// -IWmeDebugObject *CScValue::dbgGetValNative() { - return getNative(); -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgSetVal(int value) { - setInt(value); - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgSetVal(double value) { - setFloat(value); - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgSetVal(bool value) { - setBool(value); - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgSetVal(const char *value) { - setString(value); - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgSetVal() { - setNULL(); - return true; -} - - -////////////////////////////////////////////////////////////////////////// -int CScValue::dbgGetNumProperties() { - if (_valNative && _valNative->_scProp) - return _valNative->_scProp->dbgGetNumProperties(); - else return _valObject.size(); -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgGetProperty(int index, const char **name, IWmeDebugProp **value) { - if (_valNative && _valNative->_scProp) - return _valNative->_scProp->dbgGetProperty(index, name, value); - else { - int count = 0; - _valIter = _valObject.begin(); - while (_valIter != _valObject.end()) { - if (count == index) { - *name = _valIter->_key.c_str(); - *value = _valIter->_value; - return true; - } - _valIter++; - count++; - } - return false; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CScValue::dbgGetDescription(char *buf, int bufSize) { - if (_type == VAL_VARIABLE_REF) - return _valRef->dbgGetDescription(buf, bufSize); - - if (_type == VAL_NATIVE) { - _valNative->scDebuggerDesc(buf, bufSize); - } else { - strncpy(buf, getString(), bufSize); - } - return true; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/ScValue.h b/engines/wintermute/base/scriptables/ScValue.h deleted file mode 100644 index c66a60c22a..0000000000 --- a/engines/wintermute/base/scriptables/ScValue.h +++ /dev/null @@ -1,141 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BBase.h" -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/dcscript.h" // Added by ClassView -#include "engines/wintermute/wme_debugger.h" -#include "common/str.h" - -namespace WinterMute { - -class CScScript; -class CBScriptable; - -class CScValue : public CBBase, public IWmeDebugProp { -public: - bool dbgSendVariables(IWmeDebugClient *client, EWmeDebuggerVariableType type, CScScript *script, unsigned int scopeID); - - static int compare(CScValue *val1, CScValue *val2); - static int compareStrict(CScValue *val1, CScValue *val2); - TValType getTypeTolerant(); - void cleanup(bool ignoreNatives = false); - DECLARE_PERSISTENT(CScValue, CBBase) - - bool _isConstVar; - bool saveAsText(CBDynBuffer *buffer, int indent); - void setValue(CScValue *val); - bool _persistent; - bool propExists(const char *name); - void copy(CScValue *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(); - CBScriptable *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(CBScriptable *val, bool persistent = false); - void setObject(); - void setReference(CScValue *val); - bool isNULL(); - bool isNative(); - bool isString(); - bool isBool(); - bool isFloat(); - bool isInt(); - bool isObject(); - bool setProp(const char *name, CScValue *val, bool copyWhole = false, bool setAsConst = false); - CScValue *getProp(const char *name); - CBScriptable *_valNative; - CScValue *_valRef; -protected: - bool _valBool; - int _valInt; - double _valFloat; - char *_valString; -public: - TValType _type; - CScValue(CBGame *inGame); - CScValue(CBGame *inGame, bool Val); - CScValue(CBGame *inGame, int Val); - CScValue(CBGame *inGame, double Val); - CScValue(CBGame *inGame, const char *Val); - virtual ~CScValue(); - 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); - - -// IWmeDebugProp interface implementation -public: - virtual EWmeDebuggerPropType dbgGetType(); - - // getters - virtual int dbgGetValInt(); - virtual double dbgGetValFloat(); - virtual bool dbgGetValBool(); - virtual const char *dbgGetValString(); - virtual IWmeDebugObject *dbgGetValNative(); - - // setters - virtual bool dbgSetVal(int value); - virtual bool dbgSetVal(double value); - virtual bool dbgSetVal(bool value); - virtual bool dbgSetVal(const char *value); - virtual bool dbgSetVal(); - - // properties - virtual int dbgGetNumProperties(); - virtual bool dbgGetProperty(int index, const char **mame, IWmeDebugProp **value); - - virtual bool dbgGetDescription(char *buf, int bufSize); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/SxObject.cpp b/engines/wintermute/base/scriptables/SxObject.cpp deleted file mode 100644 index ba961ed2ae..0000000000 --- a/engines/wintermute/base/scriptables/SxObject.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "SxObject.h" -#include "ScValue.h" -#include "ScStack.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -IMPLEMENT_PERSISTENT(CSXObject, false) - -CBScriptable *makeSXObject(CBGame *inGame, CScStack *stack) { - return new CSXObject(inGame, stack); -} - -////////////////////////////////////////////////////////////////////////// -CSXObject::CSXObject(CBGame *inGame, CScStack *stack): CBObject(inGame) { - int numParams = stack->pop()->getInt(0); - for (int i = 0; i < numParams; i++) { - addScript(stack->pop()->getString()); - } -} - - -////////////////////////////////////////////////////////////////////////// -CSXObject::~CSXObject() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CSXObject::persist(CBPersistMgr *persistMgr) { - CBObject::persist(persistMgr); - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/SxObject.h b/engines/wintermute/base/scriptables/SxObject.h deleted file mode 100644 index b4ec7c6cde..0000000000 --- a/engines/wintermute/base/scriptables/SxObject.h +++ /dev/null @@ -1,47 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" - -namespace WinterMute { - -class CSXObject : public CBObject { -public: - DECLARE_PERSISTENT(CSXObject, CBObject) - CSXObject(CBGame *inGame, CScStack *Stack); - virtual ~CSXObject(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp new file mode 100644 index 0000000000..a9646e0045 --- /dev/null +++ b/engines/wintermute/base/scriptables/script.cpp @@ -0,0 +1,1461 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CScScript, false) + +////////////////////////////////////////////////////////////////////////// +CScScript::CScScript(CBGame *inGame, CScEngine *Engine): CBBase(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; +} + + +////////////////////////////////////////////////////////////////////////// +CScScript::~CScScript() { + cleanup(); +} + +void CScScript::readHeader() { + uint32 oldPos = _scriptStream->pos(); + _scriptStream->seek(0); + _header.magic = _scriptStream->readUint32LE(); + _header.version = _scriptStream->readUint32LE(); + _header.code_start = _scriptStream->readUint32LE(); + _header.func_table = _scriptStream->readUint32LE(); + _header.symbol_table = _scriptStream->readUint32LE(); + _header.event_table = _scriptStream->readUint32LE(); + _header.externals_table = _scriptStream->readUint32LE(); + _header.method_table = _scriptStream->readUint32LE(); + _scriptStream->seek(oldPos); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::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 CScStack(_gameRef); + _callStack = new CScStack(_gameRef); + _thisStack = new CScStack(_gameRef); + _stack = new CScStack(_gameRef); + + _operand = new CScValue(_gameRef); + _reg1 = new CScValue(_gameRef); + + + // skip to the beginning + _iP = _header.code_start; + _scriptStream->seek(_iP); + _currentLine = 0; + + // init breakpoints + _engine->refreshScriptBreakpoints(this); + + + // ready to rumble... + _state = SCRIPT_RUNNING; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::initTables() { + uint32 OrigIP = _iP; + + readHeader(); + // load symbol table + _iP = _header.symbol_table; + + _numSymbols = getDWORD(); + _symbols = new char*[_numSymbols]; + for (uint32 i = 0; i < _numSymbols; i++) { + uint32 index = getDWORD(); + _symbols[index] = getString(); + } + + // load functions table + _iP = _header.func_table; + + _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.event_table; + + _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.externals_table; + + _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.method_table; + + _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 CScScript::create(const char *filename, byte *buffer, uint32 size, CBScriptHolder *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 CScValue(_gameRef); + + _owner = owner; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::createThread(CScScript *original, uint32 initIP, const char *eventName) { + cleanup(); + + _thread = true; + _methodThread = false; + _threadEvent = new char[strlen(eventName) + 1]; + if (_threadEvent) strcpy(_threadEvent, eventName); + + // 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 CScScript::createMethodThread(CScScript *original, const char *methodName) { + uint32 ip = original->getMethodPos(methodName); + if (ip == 0) return STATUS_FAILED; + + cleanup(); + + _thread = true; + _methodThread = true; + _threadEvent = new char[strlen(methodName) + 1]; + if (_threadEvent) strcpy(_threadEvent, methodName); + + // 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 CScScript::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 CScScript::getDWORD() { + _scriptStream->seek((int32)_iP); + uint32 ret = _scriptStream->readUint32LE(); + _iP += sizeof(uint32); +// assert(oldRet == ret); + return ret; +} + +////////////////////////////////////////////////////////////////////////// +double CScScript::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 *CScScript::getString() { + char *ret = (char *)(_buffer + _iP); + while (*(char *)(_buffer + _iP) != '\0') _iP++; + _iP++; // string terminator + _scriptStream->seek(_iP); + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::executeInstruction() { + bool ret = STATUS_OK; + + uint32 dw; + const char *str = NULL; + + //CScValue* op = new CScValue(_gameRef); + _operand->cleanup(); + + CScValue *op1; + CScValue *op2; + + uint32 inst = getDWORD(); + switch (inst) { + + case II_DEF_VAR: + _operand->setNULL(); + dw = getDWORD(); + if (_scopeStack->_sP < 0) { + _globals->setProp(_symbols[dw], _operand); + if (_gameRef->getDebugMgr()->_enabled) + _gameRef->getDebugMgr()->onVariableInit(WME_DBGVAR_SCRIPT, this, NULL, _globals->getProp(_symbols[dw]), _symbols[dw]); + } else { + _scopeStack->getTop()->setProp(_symbols[dw], _operand); + if (_gameRef->getDebugMgr()->_enabled) + _gameRef->getDebugMgr()->onVariableInit(WME_DBGVAR_SCOPE, this, _scopeStack->getTop(), _scopeStack->getTop()->getProp(_symbols[dw]), _symbols[dw]); + } + + 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); + + if (_gameRef->getDebugMgr()->_enabled) + _gameRef->getDebugMgr()->onVariableInit(WME_DBGVAR_GLOBAL, this, NULL, _engine->_globals->getProp(_symbols[dw]), _symbols[dw]); + } + break; + } + + case II_RET: + if (_scopeStack->_sP >= 0 && _callStack->_sP >= 0) { + _gameRef->getDebugMgr()->onScriptShutdownScope(this, _scopeStack->getTop()); + + _scopeStack->pop(); + _iP = (uint32)_callStack->pop()->getInt(); + + if (_scopeStack->_sP < 0) _gameRef->getDebugMgr()->onScriptChangeScope(this, NULL); + else _gameRef->getDebugMgr()->onScriptChangeScope(this, _scopeStack->getTop()); + } 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); + + CScValue *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; + } + /* + CScValue* 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); + + if (_scopeStack->_sP < 0) _gameRef->getDebugMgr()->onScriptChangeScope(this, NULL); + else _gameRef->getDebugMgr()->onScriptChangeScope(this, _scopeStack->getTop()); + + 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: { + CScValue *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: { + CScValue *var = getVar(_symbols[getDWORD()]); + _operand->setReference(var); + _stack->push(_operand); + break; + } + + case II_POP_VAR: { + char *VarName = _symbols[getDWORD()]; + CScValue *var = getVar(VarName); + if (var) { + CScValue *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); + } + } + + if (_gameRef->getDebugMgr()->_enabled) + _gameRef->getDebugMgr()->onVariableChangeValue(var, 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(); + CScValue *val = _stack->pop()->getProp(str); + if (val) _stack->push(val); + else _stack->pushNULL(); + + break; + } + + case II_POP_BY_EXP: { + str = _stack->pop()->getString(); + CScValue *var = _stack->pop(); + CScValue *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); + + if (_gameRef->getDebugMgr()->_enabled) + _gameRef->getDebugMgr()->onVariableChangeValue(var, NULL); + + 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; + CScValue *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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::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(CScValue::compareStrict(op1, op2) != 0); + _stack->push(_operand); + break; + + case II_DBG_LINE: { + int newLine = getDWORD(); + if (newLine != _currentLine) { + _currentLine = newLine; + if (_gameRef->getDebugMgr()->_enabled) { + _gameRef->getDebugMgr()->onScriptChangeLine(this, _currentLine); + for (int i = 0; i < _breakpoints.getSize(); i++) { + if (_breakpoints[i] == _currentLine) { + _gameRef->getDebugMgr()->onScriptHitBreakpoint(this); + sleep(0); + break; + } + } + if (_tracingMode) { + _gameRef->getDebugMgr()->onScriptHitBreakpoint(this); + sleep(0); + break; + } + } + } + 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 CScScript::getFuncPos(const char *name) { + for (uint32 i = 0; i < _numFunctions; i++) { + if (strcmp(name, _functions[i].name) == 0) + return _functions[i].pos; + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CScScript::getMethodPos(const char *name) { + for (uint32 i = 0; i < _numMethods; i++) { + if (strcmp(name, _methods[i].name) == 0) + return _methods[i].pos; + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CScScript::getVar(char *name) { + CScValue *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); + CScValue *val = new CScValue(_gameRef); + CScValue *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 CScScript::waitFor(CBObject *object) { + if (_unbreakable) { + runtimeError("Script cannot be interrupted."); + return STATUS_OK; + } + + _state = SCRIPT_WAITING; + _waitObject = object; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::waitForExclusive(CBObject *object) { + _engine->resetObject(object); + return waitFor(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::sleep(uint32 duration) { + if (_unbreakable) { + runtimeError("Script cannot be interrupted."); + return STATUS_OK; + } + + _state = SCRIPT_SLEEPING; + if (_gameRef->_state == GAME_FROZEN) { + _waitTime = CBPlatform::getTime() + duration; + _waitFrozen = true; + } else { + _waitTime = _gameRef->_timer + duration; + _waitFrozen = false; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::finish(bool includingThreads) { + if (_state != SCRIPT_FINISHED && includingThreads) { + _state = SCRIPT_FINISHED; + finishThreads(); + } else _state = SCRIPT_FINISHED; + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::run() { + _state = SCRIPT_RUNNING; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +void CScScript::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 CScScript::persist(CBPersistMgr *persistMgr) { + + persistMgr->transfer(TMEMBER(_gameRef)); + + // buffer + if (persistMgr->_saving) { + 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->_saving) _tracingMode = false; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CScScript *CScScript::invokeEventHandler(const char *eventName, bool unbreakable) { + //if(_state!=SCRIPT_PERSISTENT) return NULL; + + uint32 pos = getEventPos(eventName); + if (!pos) return NULL; + + CScScript *thread = new CScScript(_gameRef, _engine); + if (thread) { + bool ret = thread->createThread(this, pos, eventName); + if (DID_SUCCEED(ret)) { + thread->_unbreakable = unbreakable; + _engine->_scripts.add(thread); + _gameRef->getDebugMgr()->onScriptEventThreadInit(thread, this, eventName); + return thread; + } else { + delete thread; + return NULL; + } + } else return NULL; + +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CScScript::getEventPos(const char *name) { + for (int i = _numEvents - 1; i >= 0; i--) { + if (scumm_stricmp(name, _events[i].name) == 0) return _events[i].pos; + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::canHandleEvent(const char *eventName) { + return getEventPos(eventName) != 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::canHandleMethod(const char *methodName) { + return getMethodPos(methodName) != 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::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 CScScript::resume() { + if (_state != SCRIPT_PAUSED) return STATUS_OK; + + _state = _origState; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CScScript::TExternalFunction *CScScript::getExternal(char *name) { + for (uint32 i = 0; i < _numExternals; i++) { + if (strcmp(name, _externals[i].name) == 0) + return &_externals[i]; + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::externalCall(CScStack *stack, CScStack *thisStack, CScScript::TExternalFunction *function) { + + _gameRef->LOG(0, "External functions are not supported on this platform."); + stack->correctParams(0); + stack->pushNULL(); + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::copyParameters(CScStack *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 CScScript::finishThreads() { + for (int i = 0; i < _engine->_scripts.getSize(); i++) { + CScScript *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 CScScript::dbgGetLine() { + return _currentLine; +} + +////////////////////////////////////////////////////////////////////////// +const char *CScScript::dbgGetFilename() { + return _filename; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScScript::dbgSendScript(IWmeDebugClient *client) { + if (_methodThread) client->onScriptMethodThreadInit(this, _parentScript, _threadEvent); + else if (_thread) client->onScriptEventThreadInit(this, _parentScript, _threadEvent); + else client->onScriptInit(this); + + return dbgSendVariables(client); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScScript::dbgSendVariables(IWmeDebugClient *client) { + // send script globals + _globals->dbgSendVariables(client, WME_DBGVAR_SCRIPT, this, 0); + + // send scope variables + if (_scopeStack->_sP >= 0) { + for (int i = 0; i <= _scopeStack->_sP; i++) { + // CScValue *Scope = _scopeStack->GetAt(i); + //Scope->DbgSendVariables(Client, WME_DBGVAR_SCOPE, this, (unsigned int)Scope); + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +TScriptState CScScript::dbgGetState() { + return _state; +} + +////////////////////////////////////////////////////////////////////////// +int CScScript::dbgGetNumBreakpoints() { + return _breakpoints.getSize(); +} + +////////////////////////////////////////////////////////////////////////// +int CScScript::dbgGetBreakpoint(int index) { + if (index >= 0 && index < _breakpoints.getSize()) return _breakpoints[index]; + else return -1; +} + +////////////////////////////////////////////////////////////////////////// +bool CScScript::dbgSetTracingMode(bool isTracing) { + _tracingMode = isTracing; + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool CScScript::dbgGetTracingMode() { + return _tracingMode; +} + + +////////////////////////////////////////////////////////////////////////// +void CScScript::afterLoad() { + if (_buffer == NULL) { + byte *buffer = _engine->getCompiledScript(_filename, &_bufferSize); + if (!buffer) { + _gameRef->LOG(0, "Error reinitializing script '%s' after load. Script will be terminated.", _filename); + _state = SCRIPT_ERROR; + return; + } + + _buffer = new byte [_bufferSize]; + memcpy(_buffer, buffer, _bufferSize); + + delete _scriptStream; + _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize); + + initTables(); + } +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h new file mode 100644 index 0000000000..899e1f3098 --- /dev/null +++ b/engines/wintermute/base/scriptables/script.h @@ -0,0 +1,183 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/dcscript.h" // Added by ClassView +#include "engines/wintermute/coll_templ.h" + +#include "engines/wintermute/wme_debugger.h" + +namespace WinterMute { +class CBScriptHolder; +class CBObject; +class CScEngine; +class CScStack; +class CScScript : public CBBase, public IWmeDebugScript { +public: + bool dbgSendScript(IWmeDebugClient *client); + bool dbgSendVariables(IWmeDebugClient *client); + + CBArray _breakpoints; + bool _tracingMode; + + CScScript *_parentScript; + bool _unbreakable; + bool finishThreads(); + bool copyParameters(CScStack *stack); + + void afterLoad(); + + CScValue *_operand; + CScValue *_reg1; + bool _freezable; + bool resume(); + bool pause(); + bool canHandleEvent(const char *eventName); + bool canHandleMethod(const char *methodName); + bool createThread(CScScript *original, uint32 initIP, const char *eventName); + bool createMethodThread(CScScript *original, const char *methodName); + CScScript *invokeEventHandler(const char *eventName, bool unbreakable = false); + uint32 _timeSlice; + DECLARE_PERSISTENT(CScScript, CBBase) + void runtimeError(const char *fmt, ...); + bool run(); + bool finish(bool includingThreads = false); + bool sleep(uint32 duration); + bool waitForExclusive(CBObject *object); + bool waitFor(CBObject *object); + uint32 _waitTime; + bool _waitFrozen; + CBObject *_waitObject; + CScScript *_waitScript; + TScriptState _state; + TScriptState _origState; + CScValue *getVar(char *name); + uint32 getFuncPos(const char *name); + uint32 getEventPos(const char *name); + uint32 getMethodPos(const char *name); + typedef struct { + uint32 magic; + uint32 version; + uint32 code_start; + uint32 func_table; + uint32 symbol_table; + uint32 event_table; + uint32 externals_table; + uint32 method_table; + } 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; + + + CScStack *_callStack; + CScStack *_thisStack; + CScStack *_scopeStack; + CScStack *_stack; + CScValue *_globals; + CScEngine *_engine; + int _currentLine; + bool executeInstruction(); + char *getString(); + uint32 getDWORD(); + double getFloat(); + void cleanup(); + bool create(const char *filename, byte *buffer, uint32 size, CBScriptHolder *owner); + uint32 _iP; +private: + void readHeader(); + uint32 _bufferSize; + byte *_buffer; +public: + Common::SeekableReadStream *_scriptStream; + CScScript(CBGame *inGame, CScEngine *Engine); + virtual ~CScScript(); + char *_filename; + char **_symbols; + uint32 _numSymbols; + TFunctionPos *_functions; + TMethodPos *_methods; + TEventPos *_events; + uint32 _numExternals; + TExternalFunction *_externals; + uint32 _numFunctions; + uint32 _numMethods; + uint32 _numEvents; + bool _thread; + bool _methodThread; + char *_threadEvent; + CBScriptHolder *_owner; + CScScript::TExternalFunction *getExternal(char *name); + bool externalCall(CScStack *stack, CScStack *thisStack, CScScript::TExternalFunction *function); +private: + bool initScript(); + bool initTables(); + + +// IWmeDebugScript interface implementation +public: + virtual int dbgGetLine(); + virtual const char *dbgGetFilename(); + virtual TScriptState dbgGetState(); + virtual int dbgGetNumBreakpoints(); + virtual int dbgGetBreakpoint(int Index); + + virtual bool dbgSetTracingMode(bool IsTracing); + virtual bool dbgGetTracingMode(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp new file mode 100644 index 0000000000..387093ac4a --- /dev/null +++ b/engines/wintermute/base/scriptables/script_engine.cpp @@ -0,0 +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/dcgf.h" +#include "engines/wintermute/base/scriptables/script_engine.h" +#include "engines/wintermute/utils/string_util.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_registry.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/base/base_file_manager.h" + + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CScEngine, true) + +#define COMPILER_DLL "dcscomp.dll" +////////////////////////////////////////////////////////////////////////// +CScEngine::CScEngine(CBGame *inGame): CBBase(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 CScValue(_gameRef); + + + // register 'Game' as global variable + if (!_globals->propExists("Game")) { + CScValue val(_gameRef); + val.setNative(_gameRef, true); + _globals->setProp("Game", &val); + } + + // register 'Math' as global variable + if (!_globals->propExists("Math")) { + CScValue 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(); +} + + +////////////////////////////////////////////////////////////////////////// +CScEngine::~CScEngine() { + _gameRef->LOG(0, "Shutting down scripting engine"); + saveBreakpoints(); + + disableProfiling(); + + cleanup(); + + for (int i = 0; i < _breakpoints.getSize(); i++) { + delete _breakpoints[i]; + _breakpoints[i] = NULL; + } + _breakpoints.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::cleanup() { + for (int i = 0; i < _scripts.getSize(); i++) { + if (!_scripts[i]->_thread && _scripts[i]->_owner) _scripts[i]->_owner->removeScript(_scripts[i]); + delete _scripts[i]; + _scripts.removeAt(i); + i--; + } + + _scripts.removeAll(); + + delete _globals; + _globals = NULL; + + emptyScriptCache(); + + _currentScript = NULL; // ref only + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +byte *CScEngine::loadFile(void *data, char *filename, uint32 *size) { + CBGame *gameRef = (CBGame *)data; + return gameRef->_fileManager->readWholeFile(filename, size); +} + + +////////////////////////////////////////////////////////////////////////// +void CScEngine::closeFile(void *data, byte *buffer) { + delete [] buffer; +} + + +////////////////////////////////////////////////////////////////////////// +void CScEngine::parseElement(void *data, int line, int type, void *elementData) { +} + + +////////////////////////////////////////////////////////////////////////// +CScScript *CScEngine::runScript(const char *filename, CBScriptHolder *owner) { + byte *compBuffer; + uint32 compSize; + + // get script from cache + compBuffer = getCompiledScript(filename, &compSize); + if (!compBuffer) return NULL; + + // add new script + CScScript *script = new CScScript(_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 + CScValue val(_gameRef); + if (owner)val.setNative(owner, true); + else val.setNULL(); + + script->_globals->setProp("self", &val); + script->_globals->setProp("this", &val); + + _scripts.add(script); + _gameRef->getDebugMgr()->onScriptInit(script); + + return script; + } +} + + +////////////////////////////////////////////////////////////////////////// +byte *CScEngine::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 = CBPlatform::getTime(); + *outSize = _cachedScripts[i]->_size; + return _cachedScripts[i]->_buffer; + } + } + } + + // nope, load it + byte *compBuffer; + uint32 compSize; + + uint32 size; + + byte *buffer = _gameRef->_fileManager->readWholeFile(filename, &size); + if (!buffer) { + _gameRef->LOG(0, "CScEngine::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, "CScEngine::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 = CBPlatform::getTime(); + 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 CScEngine::tick() { + if (_scripts.getSize() == 0) + return STATUS_OK; + + + // resolve waiting scripts + for (int i = 0; i < _scripts.getSize(); i++) { + + switch (_scripts[i]->_state) { + case SCRIPT_WAITING: { + /* + bool obj_found=false; + for(int j=0; j<_gameRef->_regObjects.getSize(); 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 <= CBPlatform::getTime()) _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: + //warning("CScEngine::Tick - Unhandled enum"); + break; + } // switch + } // for each script + + + // execute scripts + for (int i = 0; i < _scripts.getSize(); i++) { + + // skip paused scripts + if (_scripts[i]->_state == SCRIPT_PAUSED) continue; + + // time sliced script + if (_scripts[i]->_timeSlice > 0) { + uint32 StartTime = CBPlatform::getTime(); + while (_scripts[i]->_state == SCRIPT_RUNNING && CBPlatform::getTime() - StartTime < _scripts[i]->_timeSlice) { + _currentScript = _scripts[i]; + _scripts[i]->executeInstruction(); + } + if (_isProfiling && _scripts[i]->_filename) addScriptTime(_scripts[i]->_filename, CBPlatform::getTime() - StartTime); + } + + // normal script + else { + uint32 startTime = 0; + bool isProfiling = _isProfiling; + if (isProfiling) startTime = CBPlatform::getTime(); + + while (_scripts[i]->_state == SCRIPT_RUNNING) { + _currentScript = _scripts[i]; + _scripts[i]->executeInstruction(); + } + if (isProfiling && _scripts[i]->_filename) addScriptTime(_scripts[i]->_filename, CBPlatform::getTime() - startTime); + } + _currentScript = NULL; + } + + removeFinishedScripts(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::tickUnbreakable() { + // execute unbreakable scripts + for (int i = 0; i < _scripts.getSize(); 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 CScEngine::removeFinishedScripts() { + // remove finished scripts + for (int i = 0; i < _scripts.getSize(); 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]); + _gameRef->getDebugMgr()->onScriptShutdown(_scripts[i]); + delete _scripts[i]; + _scripts.removeAt(i); + i--; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CScEngine::getNumScripts(int *running, int *waiting, int *persistent) { + int numRunning = 0, numWaiting = 0, numPersistent = 0, numTotal = 0; + + for (int i = 0; i < _scripts.getSize(); 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("CScEngine::GetNumScripts - unhandled enum"); + break; + } + numTotal++; + } + if (running) *running = numRunning; + if (waiting) *waiting = numWaiting; + if (persistent) *persistent = numPersistent; + + return numTotal; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::emptyScriptCache() { + for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { + if (_cachedScripts[i]) { + delete _cachedScripts[i]; + _cachedScripts[i] = NULL; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::resetObject(CBObject *Object) { + // terminate all scripts waiting for this object + for (int i = 0; i < _scripts.getSize(); 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 CScEngine::resetScript(CScScript *script) { + // terminate all scripts waiting for this script + for (int i = 0; i < _scripts.getSize(); i++) { + if (_scripts[i]->_state == SCRIPT_WAITING_SCRIPT && _scripts[i]->_waitScript == script) { + _scripts[i]->finish(); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::persist(CBPersistMgr *persistMgr) { + if (!persistMgr->_saving) cleanup(); + + persistMgr->transfer(TMEMBER(_gameRef)); + persistMgr->transfer(TMEMBER(_currentScript)); + persistMgr->transfer(TMEMBER(_globals)); + _scripts.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CScEngine::editorCleanup() { + for (int i = 0; i < _scripts.getSize(); i++) { + if (_scripts[i]->_owner == NULL && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) { + delete _scripts[i]; + _scripts.removeAt(i); + i--; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::pauseAll() { + for (int i = 0; i < _scripts.getSize(); i++) { + if (_scripts[i] != _currentScript) _scripts[i]->pause(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::resumeAll() { + for (int i = 0; i < _scripts.getSize(); i++) + _scripts[i]->resume(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::isValidScript(CScScript *script) { + for (int i = 0; i < _scripts.getSize(); i++) { + if (_scripts[i] == script) return true; + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::clearGlobals(bool includingNatives) { + _globals->CleanProps(includingNatives); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::dbgSendScripts(IWmeDebugClient *client) { + // send global variables + _globals->dbgSendVariables(client, WME_DBGVAR_GLOBAL, NULL, 0); + + // process normal scripts first + for (int i = 0; i < _scripts.getSize(); i++) { + if (_scripts[i]->_thread || _scripts[i]->_methodThread) continue; + _scripts[i]->dbgSendScript(client); + } + + // and threads later + for (int i = 0; i < _scripts.getSize(); i++) { + if (_scripts[i]->_thread || _scripts[i]->_methodThread) + _scripts[i]->dbgSendScript(client); + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::addBreakpoint(const char *scriptFilename, int line) { + if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; + + CScBreakpoint *bp = NULL; + for (int i = 0; i < _breakpoints.getSize(); i++) { + if (scumm_stricmp(_breakpoints[i]->_filename.c_str(), scriptFilename) == 0) { + bp = _breakpoints[i]; + break; + } + } + if (bp == NULL) { + bp = new CScBreakpoint(scriptFilename); + _breakpoints.add(bp); + } + + for (int i = 0; i < bp->_lines.getSize(); i++) { + if (bp->_lines[i] == line) return STATUS_OK; + } + bp->_lines.add(line); + + // refresh changes + refreshScriptBreakpoints(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::removeBreakpoint(const char *scriptFilename, int line) { + if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; + + for (int i = 0; i < _breakpoints.getSize(); i++) { + if (scumm_stricmp(_breakpoints[i]->_filename.c_str(), scriptFilename) == 0) { + for (int j = 0; j < _breakpoints[i]->_lines.getSize(); j++) { + if (_breakpoints[i]->_lines[j] == line) { + _breakpoints[i]->_lines.removeAt(j); + if (_breakpoints[i]->_lines.getSize() == 0) { + delete _breakpoints[i]; + _breakpoints.removeAt(i); + } + // refresh changes + refreshScriptBreakpoints(); + + return STATUS_OK; + } + } + break; + } + } + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::refreshScriptBreakpoints() { + if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; + + for (int i = 0; i < _scripts.getSize(); i++) { + refreshScriptBreakpoints(_scripts[i]); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::refreshScriptBreakpoints(CScScript *script) { + if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; + + if (!script || !script->_filename) return STATUS_FAILED; + + for (int i = 0; i < _breakpoints.getSize(); i++) { + if (scumm_stricmp(_breakpoints[i]->_filename.c_str(), script->_filename) == 0) { + script->_breakpoints.copy(_breakpoints[i]->_lines); + return STATUS_OK; + } + } + if (script->_breakpoints.getSize() > 0) script->_breakpoints.removeAll(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::saveBreakpoints() { + if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; + + + char text[512]; + char key[100]; + + int count = 0; + for (int i = 0; i < _breakpoints.getSize(); i++) { + for (int j = 0; j < _breakpoints[i]->_lines.getSize(); j++) { + count++; + sprintf(key, "Breakpoint%d", count); + sprintf(text, "%s:%d", _breakpoints[i]->_filename.c_str(), _breakpoints[i]->_lines[j]); + + _gameRef->_registry->writeString("Debug", key, text); + } + } + _gameRef->_registry->writeInt("Debug", "NumBreakpoints", count); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CScEngine::loadBreakpoints() { + if (!_gameRef->getDebugMgr()->_enabled) return STATUS_OK; + + char key[100]; + + int count = _gameRef->_registry->readInt("Debug", "NumBreakpoints", 0); + for (int i = 1; i <= count; i++) { + /* uint32 BufSize = 512; */ + sprintf(key, "Breakpoint%d", i); + AnsiString breakpoint = _gameRef->_registry->readString("Debug", key, ""); + + char *path = CBUtils::strEntry(0, breakpoint.c_str(), ':'); + char *line = CBUtils::strEntry(1, breakpoint.c_str(), ':'); + + if (path != NULL && line != NULL) addBreakpoint(path, atoi(line)); + delete[] path; + delete[] line; + path = NULL; + line = NULL; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CScEngine::addScriptTime(const char *filename, uint32 time) { + if (!_isProfiling) return; + + AnsiString fileName = filename; + fileName.toLowercase(); + _scriptTimes[fileName] += time; +} + + +////////////////////////////////////////////////////////////////////////// +void CScEngine::enableProfiling() { + if (_isProfiling) return; + + // destroy old data, if any + _scriptTimes.clear(); + + _profilingStartTime = CBPlatform::getTime(); + _isProfiling = true; +} + + +////////////////////////////////////////////////////////////////////////// +void CScEngine::disableProfiling() { + if (!_isProfiling) return; + + dumpStats(); + _isProfiling = false; +} + + +////////////////////////////////////////////////////////////////////////// +void CScEngine::dumpStats() { + error("DumpStats not ported to ScummVM yet"); + /* uint32 totalTime = CBPlatform::getTime() - _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 new file mode 100644 index 0000000000..81dc13a73c --- /dev/null +++ b/engines/wintermute/base/scriptables/script_engine.h @@ -0,0 +1,147 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SCENGINE_H +#define WINTERMUTE_SCENGINE_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/wme_debugger.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/platform_osystem.h" + +namespace WinterMute { + +#define MAX_CACHED_SCRIPTS 20 +class CScScript; +class CScValue; +class CBObject; +class CBScriptHolder; +class CScEngine : public CBBase { +public: + class CScCachedScript { + public: + CScCachedScript(const char *filename, byte *buffer, uint32 size) { + _timestamp = CBPlatform::getTime(); + _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.removeAll(); + } + + Common::String _filename; + CBArray _lines; + }; + + + + +public: + bool dbgSendScripts(IWmeDebugClient *client); + + CBArray _breakpoints; + bool addBreakpoint(const char *scriptFilename, int line); + bool removeBreakpoint(const char *scriptFilename, int line); + bool refreshScriptBreakpoints(); + bool refreshScriptBreakpoints(CScScript *script); + bool saveBreakpoints(); + bool loadBreakpoints(); + + bool clearGlobals(bool includingNatives = false); + bool tickUnbreakable(); + bool removeFinishedScripts(); + bool isValidScript(CScScript *script); + + CScScript *_currentScript; + bool resumeAll(); + bool pauseAll(); + void editorCleanup(); + bool resetObject(CBObject *Object); + bool resetScript(CScScript *script); + bool emptyScriptCache(); + byte *getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache = false); + DECLARE_PERSISTENT(CScEngine, CBBase) + bool cleanup(); + int getNumScripts(int *running = NULL, int *waiting = NULL, int *persistent = NULL); + bool tick(); + CScValue *_globals; + CScScript *runScript(const char *filename, CBScriptHolder *owner = NULL); + static const bool _compilerAvailable = false; + + CScEngine(CBGame *inGame); + virtual ~CScEngine(); + 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); + + CBArray _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 new file mode 100644 index 0000000000..a1b8249cb1 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_array.cpp @@ -0,0 +1,238 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CSXArray, false) + +CBScriptable *makeSXArray(CBGame *inGame, CScStack *stack) { + return new CSXArray(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +CSXArray::CSXArray(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { + _length = 0; + _values = new CScValue(_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()); + } + } +} + +////////////////////////////////////////////////////////////////////////// +CSXArray::CSXArray(CBGame *inGame): CBScriptable(inGame) { + _length = 0; + _values = new CScValue(_gameRef); +} + + +////////////////////////////////////////////////////////////////////////// +CSXArray::~CSXArray() { + delete _values; + _values = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +const char *CSXArray::scToString() { + static char dummy[32768]; // TODO: Get rid of static. + strcpy(dummy, ""); + char propName[20]; + for (int i = 0; i < _length; i++) { + sprintf(propName, "%d", i); + CScValue *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, ","); + } + return dummy; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXArray::scCallMethod(CScScript *script, CScStack *stack, CScStack *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; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CSXArray::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 CSXArray::scSetProperty(const char *name, CScValue *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 CSXArray::persist(CBPersistMgr *persistMgr) { + CBScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_length)); + persistMgr->transfer(TMEMBER(_values)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXArray::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 CSXArray::push(CScValue *val) { + char paramName[20]; + _length++; + sprintf(paramName, "%d", _length - 1); + _values->setProp(paramName, val, true); + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_ext_array.h b/engines/wintermute/base/scriptables/script_ext_array.h new file mode 100644 index 0000000000..b873416572 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_array.h @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SXARRAY_H +#define WINTERMUTE_SXARRAY_H + +#include "engines/wintermute/base/base_scriptable.h" + +namespace WinterMute { + +class CSXArray : public CBScriptable { +public: + bool push(CScValue *Val); + bool validNumber(const char *origStr, char *outStr); + DECLARE_PERSISTENT(CSXArray, CBScriptable) + CSXArray(CBGame *inGame, CScStack *stack); + CSXArray(CBGame *inGame); + virtual ~CSXArray(); + CScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, CScValue *value); + bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + const char *scToString(); + int _length; + CScValue *_values; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp new file mode 100644 index 0000000000..211c0d34f0 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_date.cpp @@ -0,0 +1,297 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/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(CSXDate, false) + +CBScriptable *makeSXDate(CBGame *inGame, CScStack *stack) { + return new CSXDate(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +CSXDate::CSXDate(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { + stack->correctParams(6); + + memset(&_tm, 0, sizeof(_tm)); + + CScValue *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); + } +} + + +////////////////////////////////////////////////////////////////////////// +CSXDate::~CSXDate() { + +} + +////////////////////////////////////////////////////////////////////////// +const char *CSXDate::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(); +#if 0 + return asctime(&_tm); +#endif +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXDate::scCallMethod(CScScript *script, CScStack *stack, CScStack *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); + warning("GetWeekday returns a wrong value on purpose"); + stack->pushInt(_tm.tm_mday % 7); + 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; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CSXDate::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("date"); + return _scValue; + } + + else return _scValue; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXDate::scSetProperty(const char *name, CScValue *value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if(strcmp(name, "Name")==0){ + setName(value->getString()); + return STATUS_OK; + } + + else*/ return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXDate::persist(CBPersistMgr *persistMgr) { + + CBScriptable::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 CSXDate::scCompare(CBScriptable *Value) { + TimeDate time1 = _tm; + TimeDate time2 = ((CSXDate *)Value)->_tm; + + if (time1.tm_year < time2.tm_year) { + return -1; + } else if (time1.tm_year == time2.tm_year) { + if (time1.tm_mon < time2.tm_mon) { + return -1; + } else if (time1.tm_mon == time2.tm_mon) { + if (time1.tm_mday < time2.tm_mday) { + return -1; + } else if (time1.tm_mday == time2.tm_mday) { + if (time1.tm_hour < time2.tm_hour) { + return -1; + } else if (time1.tm_hour == time2.tm_hour) { + if (time1.tm_min < time2.tm_min) { + return -1; + } else if (time1.tm_min == time2.tm_min) { + if (time1.tm_sec < time2.tm_sec) { + return -1; + } else if (time1.tm_sec == time2.tm_sec) { + return 0; // Equal + } else { + return 1; // Sec + } + } else { + return 1; // Minute + } + } else { + return 1; // Hour + } + } else { + return 1; // Day + } + } else { + return 1; // Month + } + } else { + return 1; // Year + } +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_ext_date.h b/engines/wintermute/base/scriptables/script_ext_date.h new file mode 100644 index 0000000000..82f6af1f1d --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_date.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SXDATE_H +#define WINTERMUTE_SXDATE_H + +#include "common/system.h" +#include "engines/wintermute/base/base_scriptable.h" + +namespace WinterMute { + +class CSXDate : public CBScriptable { +public: + int scCompare(CBScriptable *Value); + DECLARE_PERSISTENT(CSXDate, CBScriptable) + CSXDate(CBGame *inGame, CScStack *Stack); + virtual ~CSXDate(); + CScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, CScValue *value); + bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + const char *scToString(); + char *_string; + TimeDate _tm; +private: + Common::String _strRep; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp new file mode 100644 index 0000000000..58c0416b43 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_file.cpp @@ -0,0 +1,779 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CSXFile, false) + +CBScriptable *makeSXFile(CBGame *inGame, CScStack *stack) { + return new CSXFile(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +CSXFile::CSXFile(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { + stack->correctParams(1); + CScValue *Val = stack->pop(); + + _filename = NULL; + if (!Val->isNULL()) CBUtils::setString(&_filename, Val->getString()); + + _readFile = NULL; + _writeFile = NULL; + + _mode = 0; + _textMode = false; +} + + +////////////////////////////////////////////////////////////////////////// +CSXFile::~CSXFile() { + cleanup(); +} + +////////////////////////////////////////////////////////////////////////// +void CSXFile::cleanup() { + delete[] _filename; + _filename = NULL; + close(); +} + + +////////////////////////////////////////////////////////////////////////// +void CSXFile::close() { + if (_readFile) { + _gameRef->_fileManager->closeFile(_readFile); + _readFile = NULL; + } + if (_writeFile) { + _writeFile->finalize(); + delete _writeFile; + _writeFile = NULL; + } + _mode = 0; + _textMode = false; +} + +////////////////////////////////////////////////////////////////////////// +const char *CSXFile::scToString() { + if (_filename) return _filename; + else return "[file object]"; +} + +#define FILE_BUFFER_SIZE 32768 +////////////////////////////////////////////////////////////////////////// +bool CSXFile::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetFilename + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetFilename") == 0) { + stack->correctParams(1); + const char *filename = stack->pop()->getString(); + cleanup(); + CBUtils::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 = _gameRef->_fileManager->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(); + stack->pushBool(CBPlatform::deleteFile(_filename) != 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(); + stack->pushBool(CBPlatform::copyFile(_filename, Dest, !Overwrite) != 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 CBScriptable::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CSXFile::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 CBScriptable::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXFile::scSetProperty(const char *name, CScValue *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 CBScriptable::scSetProperty(name, value); +} + +////////////////////////////////////////////////////////////////////////// +uint32 CSXFile::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 CSXFile::setPos(uint32 pos, int whence) { + if (_mode == 1 && _readFile) + return _readFile->seek(pos, whence); + else if ((_mode == 2 || _mode == 3) && _writeFile) { + error("CSXFile - seeking in WriteFile not supported"); + return false; +// return fseek((FILE *)_writeFile, pos, (int)origin) == 0; + } + else return false; +} + +////////////////////////////////////////////////////////////////////////// +uint32 CSXFile::getLength() { + if (_mode == 1 && _readFile) + return _readFile->size(); + else if ((_mode == 2 || _mode == 3) && _writeFile) { + error("CSXFile - 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 CSXFile::persist(CBPersistMgr *persistMgr) { + + CBScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_filename)); + persistMgr->transfer(TMEMBER(_mode)); + persistMgr->transfer(TMEMBER(_textMode)); + + uint32 pos = 0; + if (persistMgr->_saving) { + 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 = _gameRef->_fileManager->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 *CSXFile::openForWrite(const Common::String &filename, bool binary) { + error("SXFile::openForWrite - WriteFiles not supported"); +} + +// Should replace fopen(..., "ab+") and fopen(..., "a+") +Common::WriteStream *CSXFile::openForAppend(const Common::String &filename, bool binary) { + error("SXFile::openForAppend - WriteFiles not supported"); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_ext_file.h b/engines/wintermute/base/scriptables/script_ext_file.h new file mode 100644 index 0000000000..5a6811fe57 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_file.h @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTES_SXFILE_H +#define WINTERMUTES_SXFILE_H + + +#include "engines/wintermute/base/base_scriptable.h" +#include "common/stream.h" + +namespace WinterMute { + +class CBFile; + +class CSXFile : public CBScriptable { +public: + DECLARE_PERSISTENT(CSXFile, CBScriptable) + CScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, CScValue *value); + bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + const char *scToString(); + CSXFile(CBGame *inGame, CScStack *Stack); + virtual ~CSXFile(); +private: + Common::SeekableReadStream *_readFile; + Common::WriteStream *_writeFile; + int _mode; // 0..none, 1..read, 2..write, 3..append + bool _textMode; + void close(); + void cleanup(); + uint32 getPos(); + uint32 getLength(); + bool setPos(uint32 Pos, int whence = SEEK_SET); + char *_filename; + Common::WriteStream *openForWrite(const Common::String &filename, bool binary); + Common::WriteStream *openForAppend(const Common::String &filename, bool binary); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_math.cpp b/engines/wintermute/base/scriptables/script_ext_math.cpp new file mode 100644 index 0000000000..22b08087b7 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_math.cpp @@ -0,0 +1,295 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/scriptables/script_ext_math.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/persistent.h" +#include "common/math.h" +#include + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +IMPLEMENT_PERSISTENT(CSXMath, true) + +CBScriptable *makeSXMath(CBGame *inGame) { + return new CSXMath(inGame); +} + +////////////////////////////////////////////////////////////////////////// +CSXMath::CSXMath(CBGame *inGame): CBScriptable(inGame) { + +} + + +////////////////////////////////////////////////////////////////////////// +CSXMath::~CSXMath() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXMath::scCallMethod(CScScript *script, CScStack *stack, CScStack *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; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CSXMath::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 CSXMath::degreeToRadian(double value) { + return value * (M_PI / 180.0f); +} + + +////////////////////////////////////////////////////////////////////////// +double CSXMath::radianToDegree(double value) { + return value * (180.0f / M_PI); +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXMath::persist(CBPersistMgr *persistMgr) { + + CBScriptable::persist(persistMgr); + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_ext_math.h b/engines/wintermute/base/scriptables/script_ext_math.h new file mode 100644 index 0000000000..422521233f --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_math.h @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SXMATH_H +#define WINTERMUTE_SXMATH_H + + +#include "engines/wintermute/base/base_scriptable.h" + +namespace WinterMute { + +class CSXMath : public CBScriptable { +public: + DECLARE_PERSISTENT(CSXMath, CBScriptable) + CSXMath(CBGame *inGame); + virtual ~CSXMath(); + virtual CScValue *scGetProperty(const char *name); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + +private: + double degreeToRadian(double value); + double radianToDegree(double value); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp new file mode 100644 index 0000000000..df2bf188ff --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp @@ -0,0 +1,508 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CSXMemBuffer, false) + +CBScriptable *makeSXMemBuffer(CBGame *inGame, CScStack *stack) { + return new CSXMemBuffer(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +CSXMemBuffer::CSXMemBuffer(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { + stack->correctParams(1); + _buffer = NULL; + _size = 0; + + int NewSize = stack->pop()->getInt(); + resize(MAX(0, NewSize)); +} + +////////////////////////////////////////////////////////////////////////// +CSXMemBuffer::CSXMemBuffer(CBGame *inGame, void *Buffer): CBScriptable(inGame) { + _size = 0; + _buffer = Buffer; +} + + +////////////////////////////////////////////////////////////////////////// +CSXMemBuffer::~CSXMemBuffer() { + cleanup(); +} + +////////////////////////////////////////////////////////////////////////// +void *CSXMemBuffer::scToMemBuffer() { + return _buffer; +} + +////////////////////////////////////////////////////////////////////////// +void CSXMemBuffer::cleanup() { + if (_size) free(_buffer); + _buffer = NULL; + _size = 0; +} + +////////////////////////////////////////////////////////////////////////// +bool CSXMemBuffer::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 CSXMemBuffer::checkBounds(CScScript *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 *CSXMemBuffer::scToString() { + return "[membuffer object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXMemBuffer::scCallMethod(CScScript *script, CScStack *stack, CScStack *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]; + strncpy(str, (const char *)_buffer + start, length); + str[length] = '\0'; + 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); + CSXMemBuffer *buf = new CSXMemBuffer(_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(); + /* CScValue *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; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CSXMemBuffer::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 CBScriptable::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXMemBuffer::scSetProperty(const char *name, CScValue *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 CBScriptable::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXMemBuffer::persist(CBPersistMgr *persistMgr) { + + CBScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_size)); + + if (persistMgr->_saving) { + 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 CSXMemBuffer::scCompare(CBScriptable *val) { + if (_buffer == val->scToMemBuffer()) return 0; + else return 1; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h new file mode 100644 index 0000000000..a9d78e50e4 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h @@ -0,0 +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_SXMEMBUFFER_H +#define WINTERMUTE_SXMEMBUFFER_H + + +#include "engines/wintermute/base/base_scriptable.h" + +namespace WinterMute { + +class CSXMemBuffer : public CBScriptable { +public: + virtual int scCompare(CBScriptable *Val); + DECLARE_PERSISTENT(CSXMemBuffer, CBScriptable) + CScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, CScValue *value); + bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + const char *scToString(); + CSXMemBuffer(CBGame *inGame, CScStack *stack); + CSXMemBuffer(CBGame *inGame, void *buffer); + virtual ~CSXMemBuffer(); + virtual void *scToMemBuffer(); + int _size; +private: + bool resize(int newSize); + void *_buffer; + void cleanup(); + bool checkBounds(CScScript *script, int start, int length); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_object.cpp b/engines/wintermute/base/scriptables/script_ext_object.cpp new file mode 100644 index 0000000000..cb0d32d1a3 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_object.cpp @@ -0,0 +1,67 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/scriptables/script_ext_object.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CSXObject, false) + +CBScriptable *makeSXObject(CBGame *inGame, CScStack *stack) { + return new CSXObject(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +CSXObject::CSXObject(CBGame *inGame, CScStack *stack): CBObject(inGame) { + int numParams = stack->pop()->getInt(0); + for (int i = 0; i < numParams; i++) { + addScript(stack->pop()->getString()); + } +} + + +////////////////////////////////////////////////////////////////////////// +CSXObject::~CSXObject() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXObject::persist(CBPersistMgr *persistMgr) { + CBObject::persist(persistMgr); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_ext_object.h b/engines/wintermute/base/scriptables/script_ext_object.h new file mode 100644 index 0000000000..b4e869d5b3 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_object.h @@ -0,0 +1,47 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CSXObject : public CBObject { +public: + DECLARE_PERSISTENT(CSXObject, CBObject) + CSXObject(CBGame *inGame, CScStack *Stack); + virtual ~CSXObject(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp new file mode 100644 index 0000000000..bd7541fadd --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_string.cpp @@ -0,0 +1,404 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CSXString, false) + +CBScriptable *makeSXString(CBGame *inGame, CScStack *stack) { + return new CSXString(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +CSXString::CSXString(CBGame *inGame, CScStack *stack): CBScriptable(inGame) { + _string = NULL; + _capacity = 0; + + stack->correctParams(1); + CScValue *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(""); +} + + +////////////////////////////////////////////////////////////////////////// +CSXString::~CSXString() { + if (_string) delete [] _string; +} + + +////////////////////////////////////////////////////////////////////////// +void CSXString::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 *CSXString::scToString() { + if (_string) return _string; + else return "[null string]"; +} + + +////////////////////////////////////////////////////////////////////////// +void CSXString::scSetString(const char *val) { + setStringVal(val); +} + + +////////////////////////////////////////////////////////////////////////// +bool CSXString::scCallMethod(CScScript *script, CScStack *stack, CScStack *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) CBUtils::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(); + + CScValue *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); + CScValue *val = stack->pop(); + char separators[MAX_PATH_LENGTH] = ","; + if (!val->isNULL()) strcpy(separators, val->getString()); + + CSXArray *array = new CSXArray(_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 CScValue(_gameRef, StringUtil::wideToUtf8(part).c_str()); + else + val = new CScValue(_gameRef, StringUtil::wideToAnsi(part).c_str()); + + array->push(val); + delete val; + val = NULL; + } + + stack->pushNative(array, false); + return STATUS_OK; + } + + else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CSXString::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 CSXString::scSetProperty(const char *name, CScValue *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 CSXString::persist(CBPersistMgr *persistMgr) { + + CBScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_capacity)); + + if (persistMgr->_saving) { + 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 CSXString::scCompare(CBScriptable *val) { + return strcmp(_string, ((CSXString *)val)->_string); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_ext_string.h b/engines/wintermute/base/scriptables/script_ext_string.h new file mode 100644 index 0000000000..52a1524dde --- /dev/null +++ b/engines/wintermute/base/scriptables/script_ext_string.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SXSTRING_H +#define WINTERMUTE_SXSTRING_H + + +#include "engines/wintermute/base/base_scriptable.h" + +namespace WinterMute { + +class CSXString : public CBScriptable { +public: + virtual int scCompare(CBScriptable *Val); + DECLARE_PERSISTENT(CSXString, CBScriptable) + CScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, CScValue *value); + bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + void scSetString(const char *val); + const char *scToString(); + void setStringVal(const char *val); + + CSXString(CBGame *inGame, CScStack *Stack); + virtual ~CSXString(); + +private: + char *_string; + int _capacity; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_stack.cpp b/engines/wintermute/base/scriptables/script_stack.cpp new file mode 100644 index 0000000000..188cb2d15c --- /dev/null +++ b/engines/wintermute/base/scriptables/script_stack.cpp @@ -0,0 +1,226 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CScStack, false) + +////////////////////////////////////////////////////////////////////////// +CScStack::CScStack(CBGame *inGame): CBBase(inGame) { + _sP = -1; +} + + +////////////////////////////////////////////////////////////////////////// +CScStack::~CScStack() { + +#if _DEBUG + //_gameRef->LOG(0, "STAT: Stack size: %d, SP=%d", _values.getSize(), _sP); +#endif + + for (int i = 0; i < _values.getSize(); i++) { + delete _values[i]; + } + _values.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CScStack::pop() { + if (_sP < 0) { + _gameRef->LOG(0, "Fatal: Stack underflow"); + return NULL; + } + + return _values[_sP--]; +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::push(CScValue *val) { + _sP++; + + if (_sP < _values.getSize()) { + _values[_sP]->cleanup(); + _values[_sP]->copy(val); + } else { + CScValue *copyVal = new CScValue(_gameRef); + copyVal->copy(val); + _values.add(copyVal); + } +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CScStack::getPushValue() { + _sP++; + + if (_sP >= _values.getSize()) { + CScValue *val = new CScValue(_gameRef); + _values.add(val); + } + _values[_sP]->cleanup(); + return _values[_sP]; +} + + + +////////////////////////////////////////////////////////////////////////// +CScValue *CScStack::getTop() { + if (_sP < 0 || _sP >= _values.getSize()) return NULL; + else return _values[_sP]; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CScStack::getAt(int index) { + index = _sP - index; + if (index < 0 || index >= _values.getSize()) return NULL; + else return _values[index]; +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::correctParams(uint32 expectedParams) { + uint32 nuParams = (uint32)pop()->getInt(); + + if (expectedParams < nuParams) { // too many params + while (expectedParams < nuParams) { + //Pop(); + delete _values[_sP - expectedParams]; + _values.removeAt(_sP - expectedParams); + nuParams--; + _sP--; + } + } else if (expectedParams > nuParams) { // need more params + while (expectedParams > nuParams) { + //Push(null_val); + CScValue *nullVal = new CScValue(_gameRef); + nullVal->setNULL(); + _values.insertAt(_sP - nuParams + 1, nullVal); + nuParams++; + _sP++; + + if (_values.getSize() > _sP + 1) { + delete _values[_values.getSize() - 1]; + _values.removeAt(_values.getSize() - 1); + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::pushNULL() { + /* + CScValue* val = new CScValue(_gameRef); + val->setNULL(); + Push(val); + delete val; + */ + getPushValue()->setNULL(); +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::pushInt(int val) { + /* + CScValue* val = new CScValue(_gameRef); + val->setInt(Val); + Push(val); + delete val; + */ + getPushValue()->setInt(val); +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::pushFloat(double val) { + /* + CScValue* val = new CScValue(_gameRef); + val->setFloat(Val); + Push(val); + delete val; + */ + getPushValue()->setFloat(val); +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::pushBool(bool val) { + /* + CScValue* val = new CScValue(_gameRef); + val->setBool(Val); + Push(val); + delete val; + */ + getPushValue()->setBool(val); +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::pushString(const char *val) { + /* + CScValue* val = new CScValue(_gameRef); + val->setString(Val); + Push(val); + delete val; + */ + getPushValue()->setString(val); +} + + +////////////////////////////////////////////////////////////////////////// +void CScStack::pushNative(CBScriptable *val, bool persistent) { + /* + CScValue* val = new CScValue(_gameRef); + val->setNative(Val, Persistent); + Push(val); + delete val; + */ + + getPushValue()->setNative(val, persistent); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScStack::persist(CBPersistMgr *persistMgr) { + + persistMgr->transfer(TMEMBER(_gameRef)); + + persistMgr->transfer(TMEMBER(_sP)); + _values.persist(persistMgr); + + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_stack.h b/engines/wintermute/base/scriptables/script_stack.h new file mode 100644 index 0000000000..6460f901fe --- /dev/null +++ b/engines/wintermute/base/scriptables/script_stack.h @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SCSTACK_H +#define WINTERMUTE_SCSTACK_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/persistent.h" + +namespace WinterMute { + +class CScValue; +class CBScriptable; + +class CScStack : public CBBase { +public: + CScValue *getAt(int Index); + CScValue *getPushValue(); + DECLARE_PERSISTENT(CScStack, CBBase) + void pushNative(CBScriptable *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); + CScValue *getTop(); + void push(CScValue *val); + CScValue *pop(); + CScStack(CBGame *inGame); + virtual ~CScStack(); + CBArray _values; + int _sP; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp new file mode 100644 index 0000000000..da47ed299f --- /dev/null +++ b/engines/wintermute/base/scriptables/script_value.cpp @@ -0,0 +1,1054 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CScValue, false) + +////////////////////////////////////////////////////////////////////////// +CScValue::CScValue(CBGame *inGame): CBBase(inGame) { + _type = VAL_NULL; + + _valBool = false; + _valInt = 0; + _valFloat = 0.0f; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue::CScValue(CBGame *inGame, bool val): CBBase(inGame) { + _type = VAL_BOOL; + _valBool = val; + + _valInt = 0; + _valFloat = 0.0f; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue::CScValue(CBGame *inGame, int val): CBBase(inGame) { + _type = VAL_INT; + _valInt = val; + + _valFloat = 0.0f; + _valBool = false; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue::CScValue(CBGame *inGame, double val): CBBase(inGame) { + _type = VAL_FLOAT; + _valFloat = val; + + _valInt = 0; + _valBool = false; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +CScValue::CScValue(CBGame *inGame, const char *val): CBBase(inGame) { + _type = VAL_STRING; + _valString = NULL; + setStringVal(val); + + _valBool = false; + _valInt = 0; + _valFloat = 0.0f; + _valNative = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +void CScValue::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; +} + + + +////////////////////////////////////////////////////////////////////////// +CScValue::~CScValue() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CScValue::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 0 // TODO: Remove FreeType-dependency + if (_gameRef->_textEncoding == TEXT_ANSI) { +#else + if (true) { +#endif + _gameRef->_scValue->setInt(strlen(_valString)); + } else { + WideString wstr = StringUtil::utf8ToWide(_valString); + _gameRef->_scValue->setInt(wstr.size()); + } + + return _gameRef->_scValue; + } + + CScValue *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 CScValue::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 CScValue::setProp(const char *name, CScValue *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)) { + CScValue *newVal = NULL; + + _valIter = _valObject.find(name); + if (_valIter != _valObject.end()) { + newVal = _valIter->_value; + } + if (!newVal) + newVal = new CScValue(_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; + } + CScValue* val = new CScValue(_gameRef); + val->Copy(Val, CopyWhole); + val->_isConstVar = SetAsConst; + _valObject[Name] = val; + + if(_type!=VAL_NATIVE) _type = VAL_OBJECT; + */ + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::propExists(const char *name) { + if (_type == VAL_VARIABLE_REF) + return _valRef->propExists(name); + _valIter = _valObject.find(name); + + return (_valIter != _valObject.end()); +} + + +////////////////////////////////////////////////////////////////////////// +void CScValue::deleteProps() { + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + delete(CScValue *)_valIter->_value; + _valIter++; + } + _valObject.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +void CScValue::CleanProps(bool includingNatives) { + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + if (!_valIter->_value->_isConstVar && (!_valIter->_value->isNative() || includingNatives)) _valIter->_value->setNULL(); + _valIter++; + } +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::isNULL() { + if (_type == VAL_VARIABLE_REF) + return _valRef->isNULL(); + + return (_type == VAL_NULL); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::isNative() { + if (_type == VAL_VARIABLE_REF) + return _valRef->isNative(); + + return (_type == VAL_NATIVE); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::isString() { + if (_type == VAL_VARIABLE_REF) + return _valRef->isString(); + + return (_type == VAL_STRING); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::isFloat() { + if (_type == VAL_VARIABLE_REF) + return _valRef->isFloat(); + + return (_type == VAL_FLOAT); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::isInt() { + if (_type == VAL_VARIABLE_REF) + return _valRef->isInt(); + + return (_type == VAL_INT); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::isBool() { + if (_type == VAL_VARIABLE_REF) + return _valRef->isBool(); + + return (_type == VAL_BOOL); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::isObject() { + if (_type == VAL_VARIABLE_REF) + return _valRef->isObject(); + + return (_type == VAL_OBJECT); +} + + +////////////////////////////////////////////////////////////////////////// +TValType CScValue::getTypeTolerant() { + if (_type == VAL_VARIABLE_REF) + return _valRef->getType(); + + return _type; +} + + +////////////////////////////////////////////////////////////////////////// +void CScValue::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 CScValue::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 CScValue::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 CScValue::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 CScValue::setString(const Common::String &val) { + setString(val.c_str()); +} + +////////////////////////////////////////////////////////////////////////// +void CScValue::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 CScValue::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 CScValue::setNative(CBScriptable *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 CScValue::setObject() { + if (_type == VAL_VARIABLE_REF) { + _valRef->setObject(); + return; + } + + deleteProps(); + _type = VAL_OBJECT; +} + + +////////////////////////////////////////////////////////////////////////// +void CScValue::setReference(CScValue *val) { + _valRef = val; + _type = VAL_VARIABLE_REF; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::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 CScValue::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 CScValue::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 *CScValue::getMemBuffer() { + if (_type == VAL_VARIABLE_REF) + return _valRef->getMemBuffer(); + + if (_type == VAL_NATIVE) + return _valNative->scToMemBuffer(); + else return (void *)NULL; +} + + +////////////////////////////////////////////////////////////////////////// +const char *CScValue::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; +} + + +////////////////////////////////////////////////////////////////////////// +CBScriptable *CScValue::getNative() { + if (_type == VAL_VARIABLE_REF) + return _valRef->getNative(); + + if (_type == VAL_NATIVE) return _valNative; + else return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +TValType CScValue::getType() { + return _type; +} + + +////////////////////////////////////////////////////////////////////////// +void CScValue::copy(CScValue *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 CScValue(_gameRef); + _valObject[orig->_valIter->_key]->copy(orig->_valIter->_value); + orig->_valIter++; + } + } else _valObject.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +void CScValue::setValue(CScValue *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("CScValue::setValue - unhandled enum"); + break; + } + } + // otherwise just copy everything + else copy(val); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::persist(CBPersistMgr *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->_saving) { + 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 { + CScValue *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 CScValue::saveAsText(CBDynBuffer *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 CScValue::compare(CScValue *val1, CScValue *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 CScValue::compareStrict(CScValue *val1, CScValue *val2) { + if (val1->getTypeTolerant() != val2->getTypeTolerant()) return -1; + else return CScValue::compare(val1, val2); +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgSendVariables(IWmeDebugClient *client, EWmeDebuggerVariableType type, CScScript *script, unsigned int scopeID) { + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + client->onVariableInit(type, script, scopeID, _valIter->_value, _valIter->_key.c_str()); + _valIter++; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::setProperty(const char *propName, int value) { + CScValue *val = new CScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::setProperty(const char *propName, const char *value) { + CScValue *val = new CScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::setProperty(const char *propName, double value) { + CScValue *val = new CScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::setProperty(const char *propName, bool value) { + CScValue *val = new CScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CScValue::setProperty(const char *propName) { + CScValue *val = new CScValue(_gameRef); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +// IWmeDebugProp +////////////////////////////////////////////////////////////////////////// +EWmeDebuggerPropType CScValue::dbgGetType() { + switch (getType()) { + case VAL_NULL: + return WME_DBGPROP_NULL; + case VAL_STRING: + return WME_DBGPROP_STRING; + case VAL_INT: + return WME_DBGPROP_INT; + case VAL_BOOL: + return WME_DBGPROP_BOOL; + case VAL_FLOAT: + return WME_DBGPROP_FLOAT; + case VAL_OBJECT: + return WME_DBGPROP_OBJECT; + case VAL_NATIVE: + return WME_DBGPROP_NATIVE; + default: + return WME_DBGPROP_UNKNOWN; + } +} + +////////////////////////////////////////////////////////////////////////// +int CScValue::dbgGetValInt() { + return getInt(); +} + +////////////////////////////////////////////////////////////////////////// +double CScValue::dbgGetValFloat() { + return getFloat(); +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgGetValBool() { + return getBool(); +} + +////////////////////////////////////////////////////////////////////////// +const char *CScValue::dbgGetValString() { + return getString(); +} + +////////////////////////////////////////////////////////////////////////// +IWmeDebugObject *CScValue::dbgGetValNative() { + return getNative(); +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgSetVal(int value) { + setInt(value); + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgSetVal(double value) { + setFloat(value); + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgSetVal(bool value) { + setBool(value); + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgSetVal(const char *value) { + setString(value); + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgSetVal() { + setNULL(); + return true; +} + + +////////////////////////////////////////////////////////////////////////// +int CScValue::dbgGetNumProperties() { + if (_valNative && _valNative->_scProp) + return _valNative->_scProp->dbgGetNumProperties(); + else return _valObject.size(); +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgGetProperty(int index, const char **name, IWmeDebugProp **value) { + if (_valNative && _valNative->_scProp) + return _valNative->_scProp->dbgGetProperty(index, name, value); + else { + int count = 0; + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + if (count == index) { + *name = _valIter->_key.c_str(); + *value = _valIter->_value; + return true; + } + _valIter++; + count++; + } + return false; + } +} + +////////////////////////////////////////////////////////////////////////// +bool CScValue::dbgGetDescription(char *buf, int bufSize) { + if (_type == VAL_VARIABLE_REF) + return _valRef->dbgGetDescription(buf, bufSize); + + if (_type == VAL_NATIVE) { + _valNative->scDebuggerDesc(buf, bufSize); + } else { + strncpy(buf, getString(), bufSize); + } + return true; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/scriptables/script_value.h b/engines/wintermute/base/scriptables/script_value.h new file mode 100644 index 0000000000..eaee3ed773 --- /dev/null +++ b/engines/wintermute/base/scriptables/script_value.h @@ -0,0 +1,141 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SCVALUE_H +#define WINTERMUTE_SCVALUE_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/dcscript.h" // Added by ClassView +#include "engines/wintermute/wme_debugger.h" +#include "common/str.h" + +namespace WinterMute { + +class CScScript; +class CBScriptable; + +class CScValue : public CBBase, public IWmeDebugProp { +public: + bool dbgSendVariables(IWmeDebugClient *client, EWmeDebuggerVariableType type, CScScript *script, unsigned int scopeID); + + static int compare(CScValue *val1, CScValue *val2); + static int compareStrict(CScValue *val1, CScValue *val2); + TValType getTypeTolerant(); + void cleanup(bool ignoreNatives = false); + DECLARE_PERSISTENT(CScValue, CBBase) + + bool _isConstVar; + bool saveAsText(CBDynBuffer *buffer, int indent); + void setValue(CScValue *val); + bool _persistent; + bool propExists(const char *name); + void copy(CScValue *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(); + CBScriptable *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(CBScriptable *val, bool persistent = false); + void setObject(); + void setReference(CScValue *val); + bool isNULL(); + bool isNative(); + bool isString(); + bool isBool(); + bool isFloat(); + bool isInt(); + bool isObject(); + bool setProp(const char *name, CScValue *val, bool copyWhole = false, bool setAsConst = false); + CScValue *getProp(const char *name); + CBScriptable *_valNative; + CScValue *_valRef; +protected: + bool _valBool; + int _valInt; + double _valFloat; + char *_valString; +public: + TValType _type; + CScValue(CBGame *inGame); + CScValue(CBGame *inGame, bool Val); + CScValue(CBGame *inGame, int Val); + CScValue(CBGame *inGame, double Val); + CScValue(CBGame *inGame, const char *Val); + virtual ~CScValue(); + 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); + + +// IWmeDebugProp interface implementation +public: + virtual EWmeDebuggerPropType dbgGetType(); + + // getters + virtual int dbgGetValInt(); + virtual double dbgGetValFloat(); + virtual bool dbgGetValBool(); + virtual const char *dbgGetValString(); + virtual IWmeDebugObject *dbgGetValNative(); + + // setters + virtual bool dbgSetVal(int value); + virtual bool dbgSetVal(double value); + virtual bool dbgSetVal(bool value); + virtual bool dbgSetVal(const char *value); + virtual bool dbgSetVal(); + + // properties + virtual int dbgGetNumProperties(); + virtual bool dbgGetProperty(int index, const char **mame, IWmeDebugProp **value); + + virtual bool dbgGetDescription(char *buf, int bufSize); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/sound/base_sound.cpp b/engines/wintermute/base/sound/base_sound.cpp new file mode 100644 index 0000000000..e1819e3c65 --- /dev/null +++ b/engines/wintermute/base/sound/base_sound.cpp @@ -0,0 +1,288 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CBSound, false) + +////////////////////////////////////////////////////////////////////////// +CBSound::CBSound(CBGame *inGame): CBBase(inGame) { + _sound = NULL; + _soundFilename = NULL; + + _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; +} + + +////////////////////////////////////////////////////////////////////////// +CBSound::~CBSound() { + if (_sound) _gameRef->_soundMgr->removeSound(_sound); + _sound = NULL; + + delete[] _soundFilename; + _soundFilename = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::setSound(const char *filename, Audio::Mixer::SoundType type, bool streamed) { + if (_sound) { + _gameRef->_soundMgr->removeSound(_sound); + _sound = NULL; + } + delete[] _soundFilename; + _soundFilename = NULL; + + _sound = _gameRef->_soundMgr->addSound(filename, type, streamed); + if (_sound) { + _soundFilename = new char[strlen(filename) + 1]; + strcpy(_soundFilename, filename); + + _soundType = type; + _soundStreamed = streamed; + + return STATUS_OK; + } else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::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 CBSound::getLength() { + if (_sound) return _sound->getLength(); + else return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::play(bool looping) { + if (_sound) { + _soundPaused = false; + return _sound->play(looping, _soundPosition); + } else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::stop() { + if (_sound) { + _soundPaused = false; + return _sound->stop(); + } else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::pause(bool freezePaused) { + if (_sound) { + _soundPaused = true; + if (freezePaused) _sound->_freezePaused = true; + return _sound->pause(); + } else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::resume() { + if (_sound && _soundPaused) { + _soundPaused = false; + return _sound->resume(); + } else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::persist(CBPersistMgr *persistMgr) { + if (persistMgr->_saving && _sound) { + _soundPlaying = _sound->isPlaying(); + _soundLooping = _sound->_looping; + _soundPrivateVolume = _sound->_privateVolume; + if (_soundPlaying) + _soundPosition = _sound->getPosition(); + _soundLoopStart = _sound->_loopStart; + _soundFreezePaused = _sound->_freezePaused; + } + + if (persistMgr->_saving) { + _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 CBSound::isPlaying() { + return _sound && _sound->isPlaying(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::isPaused() { + return _sound && _soundPaused; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::setPositionTime(uint32 time) { + if (!_sound) return STATUS_FAILED; + _soundPosition = time; + bool ret = _sound->setPosition(_soundPosition); + if (_sound->isPlaying()) + _soundPosition = 0; + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBSound::getPositionTime() { + if (!_sound) return 0; + + if (!_sound->isPlaying()) + return 0; + else return _sound->getPosition(); +} + +////////////////////////////////////////////////////////////////////////// +bool CBSound::setVolumePercent(int percent) { + if (!_sound) + return STATUS_FAILED; + else return _sound->setPrivateVolume(percent * 255 / 100); +} + +////////////////////////////////////////////////////////////////////////// +bool CBSound::setVolume(int volume) { + if (!_sound) + return STATUS_FAILED; + else return _sound->setPrivateVolume(volume); +} + +////////////////////////////////////////////////////////////////////////// +bool CBSound::setPrivateVolume(int volume) { + if (!_sound) + return STATUS_FAILED; + else return _sound->_privateVolume = volume; +} + +////////////////////////////////////////////////////////////////////////// +int CBSound::getVolumePercent() { + if (!_sound) + return 0; + else return _sound->_privateVolume * 100 / 255; +} + +////////////////////////////////////////////////////////////////////////// +int CBSound::getVolume() { + if (!_sound) + return 0; + else return _sound->_privateVolume; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSound::setLoopStart(uint32 pos) { + if (!_sound) + return STATUS_FAILED; + else { + _sound->setLoopStart(pos); + return STATUS_OK; + } +} + +////////////////////////////////////////////////////////////////////////// +bool CBSound::setPan(float pan) { + if (_sound) + return _sound->setPan(pan); + else return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::ApplyFX(TSFXType type, float param1, float param2, float param3, float param4) { + if (!_sound) + return STATUS_OK; + + if (type != _sFXType || param1 != _sFXParam1 || param2 != _sFXParam2 || param3 != _sFXParam3 || param4 != _sFXParam4) { + bool ret = _sound->applyFX(type, param1, param2, param3, param4); + + _sFXType = type; + _sFXParam1 = param1; + _sFXParam2 = param2; + _sFXParam3 = param3; + _sFXParam4 = param4; + + return ret; + } + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/sound/base_sound.h b/engines/wintermute/base/sound/base_sound.h new file mode 100644 index 0000000000..ef52194090 --- /dev/null +++ b/engines/wintermute/base/sound/base_sound.h @@ -0,0 +1,88 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSOUND_H +#define WINTERMUTE_BSOUND_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 CBSoundBuffer; +class CBSound : public CBBase { +public: + bool setPan(float pan); + int _soundPrivateVolume; + 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 _soundPaused; + bool _soundFreezePaused; + bool isPlaying(); + bool isPaused(); + bool _soundPlaying; + bool _soundLooping; + uint32 _soundLoopStart; + uint32 _soundPosition; + DECLARE_PERSISTENT(CBSound, CBBase) + bool resume(); + bool pause(bool freezePaused = false); + bool stop(); + bool play(bool looping = false); + uint32 getLength(); + bool _soundStreamed; + Audio::Mixer::SoundType _soundType; + char *_soundFilename; + bool setSoundSimple(); + bool setSound(const char *filename, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType, bool streamed = false); + CBSound(CBGame *inGame); + virtual ~CBSound(); + + bool ApplyFX(TSFXType type = SFX_NONE, float param1 = 0, float param2 = 0, float param3 = 0, float param4 = 0); + +private: + TSFXType _sFXType; + float _sFXParam1; + float _sFXParam2; + float _sFXParam3; + float _sFXParam4; + CBSoundBuffer *_sound; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp new file mode 100644 index 0000000000..a868f99823 --- /dev/null +++ b/engines/wintermute/base/sound/base_sound_buffer.cpp @@ -0,0 +1,383 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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 "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 + +////////////////////////////////////////////////////////////////////////// +CBSoundBuffer::CBSoundBuffer(CBGame *inGame): CBBase(inGame) { + _stream = NULL; + _handle = NULL; +// _sync = NULL; + + _streamed = false; + _filename = NULL; + _file = NULL; + _privateVolume = 255; + _volume = 255; + + _looping = false; + _loopStart = 0; + + _type = Audio::Mixer::kSFXSoundType; + + _freezePaused = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBSoundBuffer::~CBSoundBuffer() { + stop(); + + if (_handle) { + g_system->getMixer()->stopHandle(*_handle); + delete _handle; + _handle = NULL; + } + delete _stream; + _stream = NULL; + + delete[] _filename; + _filename = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::setStreaming(bool Streamed, uint32 NumBlocks, uint32 BlockSize) { + _streamed = Streamed; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::loadFromFile(const char *filename, bool forceReload) { + warning("BSoundBuffer::LoadFromFile(%s,%d)", filename, forceReload); +#if 0 + if (_stream) { + BASS_StreamFree(_stream); + _stream = NULL; + } +#endif + + // Load a file, but avoid having the File-manager handle the disposal of it. + _file = _gameRef->_fileManager->openFile(filename, true, false); + if (!_file) { + _gameRef->LOG(0, "Error opening sound file '%s'", filename); + return STATUS_FAILED; + } + Common::String strFilename(filename); + 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 { + warning("BSoundBuffer::LoadFromFile - WAVE not supported yet for %s with type %d", filename, waveType); + } + } + } else { + warning("BSoundBuffer::LoadFromFile - Unknown filetype for %s", filename); + } + if (!_stream) { + return STATUS_FAILED; + } + CBUtils::setString(&_filename, filename); + + return STATUS_OK; +#if 0 + BASS_FILEPROCS fileProc; + fileProc.close = CBSoundBuffer::FileCloseProc; + fileProc.read = CBSoundBuffer::FileReadProc; + fileProc.seek = CBSoundBuffer::FileSeekProc; + fileProc.length = CBSoundBuffer::FileLenProc; + + _stream = BASS_StreamCreateFileUser(STREAMFILE_NOBUFFER, 0, &fileProc, (void *)_file); + if (!_stream) { + _gameRef->LOG(0, "BASS error: %d while loading '%s'", BASS_ErrorGetCode(), filename); + return STATUS_FAILED; + } + + CBUtils::setString(&_filename, filename); + + /* + bool res; + bool NewlyCreated = false; + + if(!_soundBuffer || ForceReload || _streamed){ + if(!_file) _file = _gameRef->_fileManager->openFile(filename); + if(!_file){ + _gameRef->LOG(0, "Error opening sound file '%s'", filename); + return STATUS_FAILED; + } + // switch to streamed for big files + if(!_streamed && (_file->GetSize() > MAX_NONSTREAMED_FILE_SIZE && !_gameRef->_forceNonStreamedSounds)) SetStreaming(true); + } + + // create buffer + if(!_soundBuffer){ + NewlyCreated = true; + + res = InitializeBuffer(_file); + if(DID_FAIL(res)){ + _gameRef->LOG(res, "Error creating sound buffer for file '%s'", filename); + return res; + } + } + + + + // store filename + if(!_filename){ + _filename = new char[strlen(filename)+1]; + strcpy(_filename, filename); + } + + // close file (if not streaming) + if(!_streamed && _file){ + _gameRef->_fileManager->closeFile(_file); + _file = NULL; + } + */ + + return STATUS_OK; +#endif +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::play(bool looping, uint32 startSample) { + if (startSample != 0) { + warning("BSoundBuffer::Play - Should start playback at %d, but currently we don't", startSample); + } + if (_handle) { + g_system->getMixer()->stopHandle(*_handle); + delete _handle; + _handle = NULL; + } + 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 CBSoundBuffer::setLooping(bool looping) { + warning("BSoundBuffer::SetLooping(%d) - won't change a playing sound", looping); + _looping = looping; +#if 0 + + + if (_stream) { + BASS_ChannelFlags(_stream, looping ? BASS_SAMPLE_LOOP : 0, BASS_SAMPLE_LOOP); + } +#endif +} + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::resume() { + if (_stream && _handle) { + g_system->getMixer()->pauseHandle(*_handle, false); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::stop() { + if (_stream && _handle) { + g_system->getMixer()->stopHandle(*_handle); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::pause() { + if (_stream && _handle) { + g_system->getMixer()->pauseHandle(*_handle, true); + } + return STATUS_OK; + +} + +////////////////////////////////////////////////////////////////////////// +uint32 CBSoundBuffer::getLength() { + if (_stream) { + uint32 len = _stream->getLength().msecs(); + return len * 1000; + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::setType(Audio::Mixer::SoundType type) { + _type = type; +} + +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::updateVolume() { + setVolume(_privateVolume); +} + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::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 CBSoundBuffer::setPrivateVolume(int volume) { + _privateVolume = volume; + return setVolume(_privateVolume); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::isPlaying() { + if (_stream && _handle) { + return _freezePaused || g_system->getMixer()->isSoundHandleActive(*_handle); + } else { + return false; + } +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBSoundBuffer::getPosition() { + if (_stream && _handle) { + uint32 pos = g_system->getMixer()->getSoundElapsedTime(*_handle); + return pos; + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::setPosition(uint32 pos) { + warning("CBSoundBuffer::SetPosition - not implemented yet"); +#if 0 + if (_stream) { + QWORD pos = BASS_ChannelSeconds2Bytes(_stream, (float)Pos / 1000.0f); + BASS_ChannelSetPosition(_stream, pos, BASS_POS_BYTE); + } +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::setLoopStart(uint32 pos) { + _loopStart = pos; +#if 0 + if (_stream) { + if (_sync) { + BASS_ChannelRemoveSync(_stream, _sync); + _sync = NULL; + } + if (_loopStart > 0) { + QWORD len = BASS_ChannelGetLength(_stream, BASS_POS_BYTE); + _sync = BASS_ChannelSetSync(_stream, BASS_SYNC_POS | BASS_SYNC_MIXTIME, len, CBSoundBuffer::LoopSyncProc, (void *)this); + } + } +#endif + return STATUS_OK; +} +#if 0 +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::LoopSyncProc(HSYNC handle, uint32 channel, uint32 data, void *user) { + CBSoundBuffer *soundBuf = static_cast(user); + QWORD pos = BASS_ChannelSeconds2Bytes(channel, (float)soundBuf->GetLoopStart() / 1000.0f); + + if (!BASS_ChannelSetPosition(channel, pos, BASS_POS_BYTE)) + BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); +} +#endif +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::setPan(float pan) { + if (_handle) { + g_system->getMixer()->setChannelBalance(*_handle, (int8)(pan * 127)); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::applyFX(TSFXType type, float param1, float param2, float param3, float param4) { + warning("CBSoundBuffer::ApplyFX - not implemented yet"); + switch (type) { + case SFX_ECHO: + break; + + case SFX_REVERB: + break; + + default: + break; + } + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/sound/base_sound_buffer.h b/engines/wintermute/base/sound/base_sound_buffer.h new file mode 100644 index 0000000000..a491bd49ad --- /dev/null +++ b/engines/wintermute/base/sound/base_sound_buffer.h @@ -0,0 +1,100 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSOUNDBUFFER_H +#define WINTERMUTE_BSOUNDBUFFER_H + + +#include "engines/wintermute/base/base.h" +#include "audio/mixer.h" +#include "common/stream.h" + +namespace Audio { +class SeekableAudioStream; +class SoundHandle; +} + +namespace WinterMute { + +class CBFile; +class CBSoundBuffer : public CBBase { +public: + + CBSoundBuffer(CBGame *inGame); + virtual ~CBSoundBuffer(); + + + 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 char *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; + Common::SeekableReadStream *_file; + char *_filename; + bool _streamed; + + int _privateVolume; +private: + int _volume; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp new file mode 100644 index 0000000000..c2174dea6a --- /dev/null +++ b/engines/wintermute/base/sound/base_sound_manager.cpp @@ -0,0 +1,292 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "engines/wintermute/base/sound/base_sound_manager.h" +#include "engines/wintermute/base/base_registry.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(CBSoundMgr, true); + +////////////////////////////////////////////////////////////////////////// +CBSoundMgr::CBSoundMgr(CBGame *inGame): CBBase(inGame) { + _soundAvailable = false; + _volumeMaster = 255; +} + + +////////////////////////////////////////////////////////////////////////// +CBSoundMgr::~CBSoundMgr() { + saveSettings(); + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundMgr::cleanup() { + for (uint32 i = 0; i < _sounds.size(); i++) + delete _sounds[i]; + _sounds.clear(); +#if 0 + BASS_Free(); +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBSoundMgr::saveSettings() { + if (_soundAvailable) { + _gameRef->_registry->writeInt("Audio", "MasterVolume", _volumeMaster); + } +} + +////////////////////////////////////////////////////////////////////////// +bool CBSoundMgr::initialize() { + _soundAvailable = false; + + if (!g_system->getMixer()->isReady()) { + return STATUS_FAILED; + } + _volumeMaster = _gameRef->_registry->readInt("Audio", "MasterVolume", 255); + _soundAvailable = true; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundMgr::initLoop() { + if (!_soundAvailable) + return STATUS_OK; +#if 0 + + BASS_Update(500); +#endif + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBSoundBuffer *CBSoundMgr::addSound(const char *filename, Audio::Mixer::SoundType type, bool streamed) { + if (!_soundAvailable) + return NULL; + + CBSoundBuffer *sound; + + // 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 (_gameRef->_fileManager->hasFile(newFile)) { + filename = newFile.c_str(); + } + } + + sound = new CBSoundBuffer(_gameRef); + if (!sound) return NULL; + + sound->setStreaming(streamed); + sound->setType(type); + + + bool res = sound->loadFromFile(filename); + if (DID_FAIL(res)) { + _gameRef->LOG(res, "Error loading sound '%s'", filename); + 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 CBSoundMgr::addSound(CBSoundBuffer *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 CBSoundMgr::removeSound(CBSoundBuffer *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 CBSoundMgr::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_wintermute->syncSoundSettings(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSoundMgr::setVolumePercent(Audio::Mixer::SoundType type, byte percent) { + return setVolume(type, percent * 255 / 100); +} + + +////////////////////////////////////////////////////////////////////////// +byte CBSoundMgr::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 CBSoundMgr::setMasterVolume(byte value) { + _volumeMaster = value; + for (uint32 i = 0; i < _sounds.size(); i++) { + _sounds[i]->updateVolume(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSoundMgr::setMasterVolumePercent(byte percent) { + setMasterVolume(percent * 255 / 100); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +byte CBSoundMgr::getMasterVolumePercent() { + return getMasterVolume() * 100 / 255; +} + +////////////////////////////////////////////////////////////////////////// +byte CBSoundMgr::getMasterVolume() { + return (byte)_volumeMaster; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundMgr::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 CBSoundMgr::resumeAll() { + + for (uint32 i = 0; i < _sounds.size(); i++) { + if (_sounds[i]->_freezePaused) { + _sounds[i]->resume(); + _sounds[i]->_freezePaused = false; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +float CBSoundMgr::posToPan(int x, int y) { + float relPos = (float)x / ((float)_gameRef->_renderer->_width); + + float minPan = -0.7f; + float maxPan = 0.7f; + + return minPan + relPos * (maxPan - minPan); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/base/sound/base_sound_manager.h b/engines/wintermute/base/sound/base_sound_manager.h new file mode 100644 index 0000000000..2c05bbfcb8 --- /dev/null +++ b/engines/wintermute/base/sound/base_sound_manager.h @@ -0,0 +1,69 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSOUNDMGR_H +#define WINTERMUTE_BSOUNDMGR_H + +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base.h" +#include "audio/mixer.h" +#include "common/array.h" + +namespace WinterMute { +class CBSoundBuffer; +class CBSoundMgr : public CBBase { +public: + float posToPan(int x, int y); + bool resumeAll(); + bool pauseAll(bool includingMusic = true); + bool cleanup(); + //DECLARE_PERSISTENT(CBSoundMgr, CBBase); + 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(CBSoundBuffer *sound); + CBSoundBuffer *addSound(const char *filename, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType, bool streamed = false); + bool addSound(CBSoundBuffer *sound, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType); + bool initLoop(); + bool initialize(); + bool _soundAvailable; + CBSoundMgr(CBGame *inGame); + virtual ~CBSoundMgr(); + 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 e0d7ad8132..865e60b447 100644 --- a/engines/wintermute/coll_templ.h +++ b/engines/wintermute/coll_templ.h @@ -31,10 +31,12 @@ #include -#include "engines/wintermute/base/BPersistMgr.h" +#include "engines/wintermute/base/base_persistence_manager.h" namespace WinterMute { +// Quite the same as Common::Array, but with persistence-support. + ///////////////////////////////////////////////////////////////////////////// template inline void DCConstructElements(TYPE *pElements, int nCount) { diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index e3fbb15d3f..0abe78fa35 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -22,7 +22,7 @@ #include "engines/advancedDetector.h" #include "engines/wintermute/wintermute.h" -#include "engines/wintermute/base/BPersistMgr.h" +#include "engines/wintermute/base/base_persistence_manager.h" #include "common/config-manager.h" #include "common/error.h" diff --git a/engines/wintermute/graphics/transparentSurface.cpp b/engines/wintermute/graphics/transparentSurface.cpp deleted file mode 100644 index a99138ade6..0000000000 --- a/engines/wintermute/graphics/transparentSurface.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "common/algorithm.h" -#include "common/endian.h" -#include "common/util.h" -#include "common/rect.h" -#include "common/textconsole.h" -#include "graphics/primitives.h" -#include "engines/wintermute/graphics/transparentSurface.h" - -namespace WinterMute { - -TransparentSurface::TransparentSurface() : Surface() {} - -TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface() { - if (copyData) { - copyFrom(surf); - } else { - w = surf.w; - h = surf.h; - pitch = surf.pitch; - format = surf.format; - pixels = surf.pixels; - } -} - -void doBlit(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { - byte *in, *out; - -#ifdef SCUMM_LITTLE_ENDIAN - const int aIndex = 0; - const int bIndex = 1; - const int gIndex = 2; - const int rIndex = 3; -#else - const int aIndex = 3; - const int bIndex = 2; - const int gIndex = 1; - const int rIndex = 0; -#endif - - const int bShift = 8;//img->format.bShift; - const int gShift = 16;//img->format.gShift; - const int rShift = 24;//img->format.rShift; - const int aShift = 0;//img->format.aShift; - - const int bShiftTarget = 8;//target.format.bShift; - const int gShiftTarget = 16;//target.format.gShift; - const int rShiftTarget = 24;//target.format.rShift; - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - uint32 pix = *(uint32 *)in; - uint32 o_pix = *(uint32 *) out; - int b = (pix >> bShift) & 0xff; - int g = (pix >> gShift) & 0xff; - int r = (pix >> rShift) & 0xff; - int a = (pix >> aShift) & 0xff; - int o_b, o_g, o_r, o_a; - in += inStep; - - /* if (ca != 255) { - a = a * ca >> 8; - }*/ - - switch (a) { - case 0: // Full transparency - out += 4; - break; - case 255: // Full opacity - o_b = b; - o_g = g; - o_r = r; - o_a = a; - //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); - out[aIndex] = o_a; - out[bIndex] = o_b; - out[gIndex] = o_g; - out[rIndex] = o_r; - out += 4; - break; - - default: // alpha blending - o_a = 255; - o_b = (o_pix >> bShiftTarget) & 0xff; - o_g = (o_pix >> gShiftTarget) & 0xff; - o_r = (o_pix >> rShiftTarget) & 0xff; - o_b += ((b - o_b) * a) >> 8; - o_g += ((g - o_g) * a) >> 8; - o_r += ((r - o_r) * a) >> 8; - //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); - out[aIndex] = o_a; - out[bIndex] = o_b; - out[gIndex] = o_g; - out[rIndex] = o_r; - out += 4; - } - } - outo += pitch; - ino += inoStep; - } -} - - -Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) { - int ca = (color >> 24) & 0xff; - - Common::Rect retSize; - retSize.top = 0; - retSize.left = 0; - retSize.setWidth(0); - retSize.setHeight(0); - // Check if we need to draw anything at all - if (ca == 0) - return retSize; - - int cr = (color >> 16) & 0xff; - int cg = (color >> 8) & 0xff; - int cb = (color >> 0) & 0xff; - - // Compensate for transparency. Since we're coming - // down to 255 alpha, we just compensate for the colors here - if (ca != 255) { - cr = cr * ca >> 8; - cg = cg * ca >> 8; - cb = cb * ca >> 8; - } - - // Create an encapsulating surface for the data - TransparentSurface srcImage(*this, false); - // TODO: Is the data really in the screen format? - if (format.bytesPerPixel != 4) { - warning("TransparentSurface can only blit 32 bpp images"); - return retSize; - } - - if (pPartRect) { - srcImage.pixels = &((char *)pixels)[pPartRect->top * srcImage.pitch + pPartRect->left * 4]; - srcImage.w = pPartRect->width(); - srcImage.h = pPartRect->height(); - - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, - pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); - } else { - - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, - srcImage.w, srcImage.h, color, width, height); - } - - if (width == -1) - width = srcImage.w; - if (height == -1) - height = srcImage.h; - -#ifdef SCALING_TESTING - // Hardcode scaling to 66% to test scaling - width = width * 2 / 3; - height = height * 2 / 3; -#endif - - Graphics::Surface *img; - Graphics::Surface *imgScaled = NULL; - byte *savedPixels = NULL; - if ((width != srcImage.w) || (height != srcImage.h)) { - // Scale the image - img = imgScaled = srcImage.scale(width, height); - savedPixels = (byte *)img->pixels; - } else { - img = &srcImage; - } - - // Handle off-screen clipping - if (posY < 0) { - img->h = MAX(0, (int)img->h - -posY); - img->pixels = (byte *)img->pixels + img->pitch * -posY; - posY = 0; - } - - if (posX < 0) { - img->w = MAX(0, (int)img->w - -posX); - img->pixels = (byte *)img->pixels + (-posX * 4); - posX = 0; - } - - img->w = CLIP((int)img->w, 0, (int)MAX((int)target.w - posX, 0)); - img->h = CLIP((int)img->h, 0, (int)MAX((int)target.h - posY, 0)); - - if ((img->w > 0) && (img->h > 0)) { - int xp = 0, yp = 0; - - int inStep = 4; - int inoStep = img->pitch; - if (flipping & TransparentSurface::FLIP_V) { - inStep = -inStep; - xp = img->w - 1; - } - - if (flipping & TransparentSurface::FLIP_H) { - inoStep = -inoStep; - yp = img->h - 1; - } - - byte *ino = (byte *)img->getBasePtr(xp, yp); - byte *outo = (byte *)target.getBasePtr(posX, posY); - byte *in, *out; - -#ifdef SCUMM_LITTLE_ENDIAN - const int aIndex = 0; - const int bIndex = 1; - const int gIndex = 2; - const int rIndex = 3; -#else - const int aIndex = 3; - const int bIndex = 2; - const int gIndex = 1; - const int rIndex = 0; -#endif - - const int bShift = 8;//img->format.bShift; - const int gShift = 16;//img->format.gShift; - const int rShift = 24;//img->format.rShift; - const int aShift = 0;//img->format.aShift; - - const int bShiftTarget = 8;//target.format.bShift; - const int gShiftTarget = 16;//target.format.gShift; - const int rShiftTarget = 24;//target.format.rShift; - - if (ca == 255 && cb == 255 && cg == 255 && cr == 255) { - doBlit(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); - } else { - for (int i = 0; i < img->h; i++) { - out = outo; - in = ino; - for (int j = 0; j < img->w; j++) { - uint32 pix = *(uint32 *)in; - uint32 o_pix = *(uint32 *) out; - int b = (pix >> bShift) & 0xff; - int g = (pix >> gShift) & 0xff; - int r = (pix >> rShift) & 0xff; - int a = (pix >> aShift) & 0xff; - int o_b, o_g, o_r, o_a; - in += inStep; - - if (ca != 255) { - a = a * ca >> 8; - } - - switch (a) { - case 0: // Full transparency - out += 4; - break; - case 255: // Full opacity - if (cb != 255) - o_b = (b * cb) >> 8; - else - o_b = b; - - if (cg != 255) - o_g = (g * cg) >> 8; - else - o_g = g; - - if (cr != 255) - o_r = (r * cr) >> 8; - else - o_r = r; - o_a = a; - //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); - out[aIndex] = o_a; - out[bIndex] = o_b; - out[gIndex] = o_g; - out[rIndex] = o_r; - out += 4; - break; - - default: // alpha blending - o_a = 255; - o_b = (o_pix >> bShiftTarget) & 0xff; - o_g = (o_pix >> gShiftTarget) & 0xff; - o_r = (o_pix >> rShiftTarget) & 0xff; - if (cb == 0) - o_b = 0; - else if (cb != 255) - o_b += ((b - o_b) * a * cb) >> 16; - else - o_b += ((b - o_b) * a) >> 8; - if (cg == 0) - o_g = 0; - else if (cg != 255) - o_g += ((g - o_g) * a * cg) >> 16; - else - o_g += ((g - o_g) * a) >> 8; - if (cr == 0) - o_r = 0; - else if (cr != 255) - o_r += ((r - o_r) * a * cr) >> 16; - else - o_r += ((r - o_r) * a) >> 8; - //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); - out[aIndex] = o_a; - out[bIndex] = o_b; - out[gIndex] = o_g; - out[rIndex] = o_r; - out += 4; - } - } - outo += target.pitch; - ino += inoStep; - } - } - } - - if (imgScaled) { - imgScaled->pixels = savedPixels; - imgScaled->free(); - delete imgScaled; - } - - retSize.setWidth(img->w); - retSize.setHeight(img->h); - return retSize; -} - -/** - * Scales a passed surface, creating a new surface with the result - * @param srcImage Source image to scale - * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero) - * @remarks Caller is responsible for freeing the returned surface - */ -TransparentSurface *TransparentSurface::scale(int xSize, int ySize) const { - TransparentSurface *s = new TransparentSurface(); - s->create(xSize, ySize, this->format); - - int *horizUsage = scaleLine(xSize, this->w); - int *vertUsage = scaleLine(ySize, this->h); - - // Loop to create scaled version - for (int yp = 0; yp < ySize; ++yp) { - const byte *srcP = (const byte *)this->getBasePtr(0, vertUsage[yp]); - byte *destP = (byte *)s->getBasePtr(0, yp); - - for (int xp = 0; xp < xSize; ++xp) { - const byte *tempSrcP = srcP + (horizUsage[xp] * this->format.bytesPerPixel); - for (int byteCtr = 0; byteCtr < this->format.bytesPerPixel; ++byteCtr) { - *destP++ = *tempSrcP++; - } - } - } - - // Delete arrays and return surface - delete[] horizUsage; - delete[] vertUsage; - return s; -} - -/** - * Writes a color key to the alpha channel of the surface - * @param rKey the red component of the color key - * @param gKey the green component of the color key - * @param bKey the blue component of the color key - * @param overwriteAlpha if true, all other alpha will be set fully opaque - */ -void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) { - assert(format.bytesPerPixel == 4); - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - uint32 pix = ((uint32 *)pixels)[i * w + j]; - uint8 r, g, b, a; - format.colorToARGB(pix, a, r, g, b); - if (r == rKey && g == gKey && b == bKey) { - a = 0; - ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); - } else if (overwriteAlpha) { - a = 255; - ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); - } - } - } -} - -/** - * Returns an array indicating which pixels of a source image horizontally or vertically get - * included in a scaled image - */ -int *TransparentSurface::scaleLine(int size, int srcSize) { - int scale = 100 * size / srcSize; - assert(scale > 0); - int *v = new int[size]; - Common::fill(v, &v[size], 0); - - int distCtr = 0; - int *destP = v; - for (int distIndex = 0; distIndex < srcSize; ++distIndex) { - distCtr += scale; - while (distCtr >= 100) { - assert(destP < &v[size]); - *destP++ = distIndex; - distCtr -= 100; - } - } - - return v; -} - - -} // End of namespace Graphics diff --git a/engines/wintermute/graphics/transparentSurface.h b/engines/wintermute/graphics/transparentSurface.h deleted file mode 100644 index e271bf2488..0000000000 --- a/engines/wintermute/graphics/transparentSurface.h +++ /dev/null @@ -1,124 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef GRAPHICS_TRANSPARENTSURFACE_H -#define GRAPHICS_TRANSPARENTSURFACE_H - -#include "graphics/surface.h" - -/* - * This code is based on Broken Sword 2.5 engine - * - * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer - * - * Licensed under GNU GPL v2 - * - */ - -// TODO: Find a better solution for this. -#define BS_RGB(R,G,B) (0xFF000000 | ((R) << 16) | ((G) << 8) | (B)) -#define BS_ARGB(A,R,G,B) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) - -namespace WinterMute { - -/** - * A transparent graphics surface, which implements alpha blitting. - */ -struct TransparentSurface : public Graphics::Surface { - TransparentSurface(); - TransparentSurface(const Graphics::Surface &surf, bool copyData = false); - - void setColorKey(char r, char g, char b); - void disableColorKey(); - - // Enums - /** - @brief The possible flipping parameters for the blit methode. - */ - enum FLIP_FLAGS { - /// The image will not be flipped. - FLIP_NONE = 0, - /// The image will be flipped at the horizontal axis. - FLIP_H = 1, - /// The image will be flipped at the vertical axis. - FLIP_V = 2, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_HV = FLIP_H | FLIP_V, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_VH = FLIP_H | FLIP_V - }; - - /** - @brief renders the surface to another surface - @param pDest a pointer to the target image. In most cases this is the framebuffer. - @param PosX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.
- The default value is 0. - @param PosY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.
- The default value is 0. - @param Flipping how the the image should be flipped.
- The default value is BS_Image::FLIP_NONE (no flipping) - @param pSrcPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.
- This referes to the unflipped and unscaled image.
- The default value is NULL. - @param Color an ARGB color value, which determines the parameters for the color modulation und alpha blending.
- The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).
- The color components determines the color for color modulation.
- The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation). - The macros BS_RGB and BS_ARGB can be used for the creation of the color value. - @param Width the output width of the screen section. - The images will be scaled if the output width of the screen section differs from the image section.
- The value -1 determines that the image should not be scaled.
- The default value is -1. - @param Width the output height of the screen section. - The images will be scaled if the output width of the screen section differs from the image section.
- The value -1 determines that the image should not be scaled.
- The default value is -1. - @return returns false if the rendering failed. - */ - - Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0, - int flipping = FLIP_NONE, - Common::Rect *pPartRect = NULL, - uint color = BS_ARGB(255, 255, 255, 255), - int width = -1, int height = -1); - void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); - TransparentSurface *scale(int xSize, int ySize) const; -private: - static int *scaleLine(int size, int srcSize); -}; - -/** - * A deleter for Surface objects which can be used with SharedPtr. - * - * This deleter assures Surface::free is called on deletion. - */ -/*struct SharedPtrTransparentSurfaceDeleter { - void operator()(TransparentSurface *ptr) { - ptr->free(); - delete ptr; - } -};*/ - - -} // End of namespace Graphics - - -#endif diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp new file mode 100644 index 0000000000..6ab9c621d0 --- /dev/null +++ b/engines/wintermute/graphics/transparent_surface.cpp @@ -0,0 +1,427 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "common/algorithm.h" +#include "common/endian.h" +#include "common/util.h" +#include "common/rect.h" +#include "common/textconsole.h" +#include "graphics/primitives.h" +#include "engines/wintermute/graphics/transparent_surface.h" + +namespace WinterMute { + +TransparentSurface::TransparentSurface() : Surface() {} + +TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface() { + if (copyData) { + copyFrom(surf); + } else { + w = surf.w; + h = surf.h; + pitch = surf.pitch; + format = surf.format; + pixels = surf.pixels; + } +} + +void doBlit(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { + byte *in, *out; + +#ifdef SCUMM_LITTLE_ENDIAN + const int aIndex = 0; + const int bIndex = 1; + const int gIndex = 2; + const int rIndex = 3; +#else + const int aIndex = 3; + const int bIndex = 2; + const int gIndex = 1; + const int rIndex = 0; +#endif + + const int bShift = 8;//img->format.bShift; + const int gShift = 16;//img->format.gShift; + const int rShift = 24;//img->format.rShift; + const int aShift = 0;//img->format.aShift; + + const int bShiftTarget = 8;//target.format.bShift; + const int gShiftTarget = 16;//target.format.gShift; + const int rShiftTarget = 24;//target.format.rShift; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + uint32 pix = *(uint32 *)in; + uint32 o_pix = *(uint32 *) out; + int b = (pix >> bShift) & 0xff; + int g = (pix >> gShift) & 0xff; + int r = (pix >> rShift) & 0xff; + int a = (pix >> aShift) & 0xff; + int o_b, o_g, o_r, o_a; + in += inStep; + + /* if (ca != 255) { + a = a * ca >> 8; + }*/ + + switch (a) { + case 0: // Full transparency + out += 4; + break; + case 255: // Full opacity + o_b = b; + o_g = g; + o_r = r; + o_a = a; + //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); + out[aIndex] = o_a; + out[bIndex] = o_b; + out[gIndex] = o_g; + out[rIndex] = o_r; + out += 4; + break; + + default: // alpha blending + o_a = 255; + o_b = (o_pix >> bShiftTarget) & 0xff; + o_g = (o_pix >> gShiftTarget) & 0xff; + o_r = (o_pix >> rShiftTarget) & 0xff; + o_b += ((b - o_b) * a) >> 8; + o_g += ((g - o_g) * a) >> 8; + o_r += ((r - o_r) * a) >> 8; + //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); + out[aIndex] = o_a; + out[bIndex] = o_b; + out[gIndex] = o_g; + out[rIndex] = o_r; + out += 4; + } + } + outo += pitch; + ino += inoStep; + } +} + + +Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) { + int ca = (color >> 24) & 0xff; + + Common::Rect retSize; + retSize.top = 0; + retSize.left = 0; + retSize.setWidth(0); + retSize.setHeight(0); + // Check if we need to draw anything at all + if (ca == 0) + return retSize; + + int cr = (color >> 16) & 0xff; + int cg = (color >> 8) & 0xff; + int cb = (color >> 0) & 0xff; + + // Compensate for transparency. Since we're coming + // down to 255 alpha, we just compensate for the colors here + if (ca != 255) { + cr = cr * ca >> 8; + cg = cg * ca >> 8; + cb = cb * ca >> 8; + } + + // Create an encapsulating surface for the data + TransparentSurface srcImage(*this, false); + // TODO: Is the data really in the screen format? + if (format.bytesPerPixel != 4) { + warning("TransparentSurface can only blit 32 bpp images"); + return retSize; + } + + if (pPartRect) { + srcImage.pixels = &((char *)pixels)[pPartRect->top * srcImage.pitch + pPartRect->left * 4]; + srcImage.w = pPartRect->width(); + srcImage.h = pPartRect->height(); + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, + pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); + } else { + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, + srcImage.w, srcImage.h, color, width, height); + } + + if (width == -1) + width = srcImage.w; + if (height == -1) + height = srcImage.h; + +#ifdef SCALING_TESTING + // Hardcode scaling to 66% to test scaling + width = width * 2 / 3; + height = height * 2 / 3; +#endif + + Graphics::Surface *img; + Graphics::Surface *imgScaled = NULL; + byte *savedPixels = NULL; + if ((width != srcImage.w) || (height != srcImage.h)) { + // Scale the image + img = imgScaled = srcImage.scale(width, height); + savedPixels = (byte *)img->pixels; + } else { + img = &srcImage; + } + + // Handle off-screen clipping + if (posY < 0) { + img->h = MAX(0, (int)img->h - -posY); + img->pixels = (byte *)img->pixels + img->pitch * -posY; + posY = 0; + } + + if (posX < 0) { + img->w = MAX(0, (int)img->w - -posX); + img->pixels = (byte *)img->pixels + (-posX * 4); + posX = 0; + } + + img->w = CLIP((int)img->w, 0, (int)MAX((int)target.w - posX, 0)); + img->h = CLIP((int)img->h, 0, (int)MAX((int)target.h - posY, 0)); + + if ((img->w > 0) && (img->h > 0)) { + int xp = 0, yp = 0; + + int inStep = 4; + int inoStep = img->pitch; + if (flipping & TransparentSurface::FLIP_V) { + inStep = -inStep; + xp = img->w - 1; + } + + if (flipping & TransparentSurface::FLIP_H) { + inoStep = -inoStep; + yp = img->h - 1; + } + + byte *ino = (byte *)img->getBasePtr(xp, yp); + byte *outo = (byte *)target.getBasePtr(posX, posY); + byte *in, *out; + +#ifdef SCUMM_LITTLE_ENDIAN + const int aIndex = 0; + const int bIndex = 1; + const int gIndex = 2; + const int rIndex = 3; +#else + const int aIndex = 3; + const int bIndex = 2; + const int gIndex = 1; + const int rIndex = 0; +#endif + + const int bShift = 8;//img->format.bShift; + const int gShift = 16;//img->format.gShift; + const int rShift = 24;//img->format.rShift; + const int aShift = 0;//img->format.aShift; + + const int bShiftTarget = 8;//target.format.bShift; + const int gShiftTarget = 16;//target.format.gShift; + const int rShiftTarget = 24;//target.format.rShift; + + if (ca == 255 && cb == 255 && cg == 255 && cr == 255) { + doBlit(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); + } else { + for (int i = 0; i < img->h; i++) { + out = outo; + in = ino; + for (int j = 0; j < img->w; j++) { + uint32 pix = *(uint32 *)in; + uint32 o_pix = *(uint32 *) out; + int b = (pix >> bShift) & 0xff; + int g = (pix >> gShift) & 0xff; + int r = (pix >> rShift) & 0xff; + int a = (pix >> aShift) & 0xff; + int o_b, o_g, o_r, o_a; + in += inStep; + + if (ca != 255) { + a = a * ca >> 8; + } + + switch (a) { + case 0: // Full transparency + out += 4; + break; + case 255: // Full opacity + if (cb != 255) + o_b = (b * cb) >> 8; + else + o_b = b; + + if (cg != 255) + o_g = (g * cg) >> 8; + else + o_g = g; + + if (cr != 255) + o_r = (r * cr) >> 8; + else + o_r = r; + o_a = a; + //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); + out[aIndex] = o_a; + out[bIndex] = o_b; + out[gIndex] = o_g; + out[rIndex] = o_r; + out += 4; + break; + + default: // alpha blending + o_a = 255; + o_b = (o_pix >> bShiftTarget) & 0xff; + o_g = (o_pix >> gShiftTarget) & 0xff; + o_r = (o_pix >> rShiftTarget) & 0xff; + if (cb == 0) + o_b = 0; + else if (cb != 255) + o_b += ((b - o_b) * a * cb) >> 16; + else + o_b += ((b - o_b) * a) >> 8; + if (cg == 0) + o_g = 0; + else if (cg != 255) + o_g += ((g - o_g) * a * cg) >> 16; + else + o_g += ((g - o_g) * a) >> 8; + if (cr == 0) + o_r = 0; + else if (cr != 255) + o_r += ((r - o_r) * a * cr) >> 16; + else + o_r += ((r - o_r) * a) >> 8; + //*(uint32 *)out = target.format.ARGBToColor(o_a, o_r, o_g, o_b); + out[aIndex] = o_a; + out[bIndex] = o_b; + out[gIndex] = o_g; + out[rIndex] = o_r; + out += 4; + } + } + outo += target.pitch; + ino += inoStep; + } + } + } + + if (imgScaled) { + imgScaled->pixels = savedPixels; + imgScaled->free(); + delete imgScaled; + } + + retSize.setWidth(img->w); + retSize.setHeight(img->h); + return retSize; +} + +/** + * Scales a passed surface, creating a new surface with the result + * @param srcImage Source image to scale + * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero) + * @remarks Caller is responsible for freeing the returned surface + */ +TransparentSurface *TransparentSurface::scale(int xSize, int ySize) const { + TransparentSurface *s = new TransparentSurface(); + s->create(xSize, ySize, this->format); + + int *horizUsage = scaleLine(xSize, this->w); + int *vertUsage = scaleLine(ySize, this->h); + + // Loop to create scaled version + for (int yp = 0; yp < ySize; ++yp) { + const byte *srcP = (const byte *)this->getBasePtr(0, vertUsage[yp]); + byte *destP = (byte *)s->getBasePtr(0, yp); + + for (int xp = 0; xp < xSize; ++xp) { + const byte *tempSrcP = srcP + (horizUsage[xp] * this->format.bytesPerPixel); + for (int byteCtr = 0; byteCtr < this->format.bytesPerPixel; ++byteCtr) { + *destP++ = *tempSrcP++; + } + } + } + + // Delete arrays and return surface + delete[] horizUsage; + delete[] vertUsage; + return s; +} + +/** + * Writes a color key to the alpha channel of the surface + * @param rKey the red component of the color key + * @param gKey the green component of the color key + * @param bKey the blue component of the color key + * @param overwriteAlpha if true, all other alpha will be set fully opaque + */ +void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) { + assert(format.bytesPerPixel == 4); + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + uint32 pix = ((uint32 *)pixels)[i * w + j]; + uint8 r, g, b, a; + format.colorToARGB(pix, a, r, g, b); + if (r == rKey && g == gKey && b == bKey) { + a = 0; + ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); + } else if (overwriteAlpha) { + a = 255; + ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); + } + } + } +} + +/** + * Returns an array indicating which pixels of a source image horizontally or vertically get + * included in a scaled image + */ +int *TransparentSurface::scaleLine(int size, int srcSize) { + int scale = 100 * size / srcSize; + assert(scale > 0); + int *v = new int[size]; + Common::fill(v, &v[size], 0); + + int distCtr = 0; + int *destP = v; + for (int distIndex = 0; distIndex < srcSize; ++distIndex) { + distCtr += scale; + while (distCtr >= 100) { + assert(destP < &v[size]); + *destP++ = distIndex; + distCtr -= 100; + } + } + + return v; +} + + +} // End of namespace Graphics diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h new file mode 100644 index 0000000000..e271bf2488 --- /dev/null +++ b/engines/wintermute/graphics/transparent_surface.h @@ -0,0 +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. + */ + +#ifndef GRAPHICS_TRANSPARENTSURFACE_H +#define GRAPHICS_TRANSPARENTSURFACE_H + +#include "graphics/surface.h" + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +// TODO: Find a better solution for this. +#define BS_RGB(R,G,B) (0xFF000000 | ((R) << 16) | ((G) << 8) | (B)) +#define BS_ARGB(A,R,G,B) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) + +namespace WinterMute { + +/** + * A transparent graphics surface, which implements alpha blitting. + */ +struct TransparentSurface : public Graphics::Surface { + TransparentSurface(); + TransparentSurface(const Graphics::Surface &surf, bool copyData = false); + + void setColorKey(char r, char g, char b); + void disableColorKey(); + + // Enums + /** + @brief The possible flipping parameters for the blit methode. + */ + enum FLIP_FLAGS { + /// The image will not be flipped. + FLIP_NONE = 0, + /// The image will be flipped at the horizontal axis. + FLIP_H = 1, + /// The image will be flipped at the vertical axis. + FLIP_V = 2, + /// The image will be flipped at the horizontal and vertical axis. + FLIP_HV = FLIP_H | FLIP_V, + /// The image will be flipped at the horizontal and vertical axis. + FLIP_VH = FLIP_H | FLIP_V + }; + + /** + @brief renders the surface to another surface + @param pDest a pointer to the target image. In most cases this is the framebuffer. + @param PosX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.
+ The default value is 0. + @param PosY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.
+ The default value is 0. + @param Flipping how the the image should be flipped.
+ The default value is BS_Image::FLIP_NONE (no flipping) + @param pSrcPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.
+ This referes to the unflipped and unscaled image.
+ The default value is NULL. + @param Color an ARGB color value, which determines the parameters for the color modulation und alpha blending.
+ The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).
+ The color components determines the color for color modulation.
+ The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation). + The macros BS_RGB and BS_ARGB can be used for the creation of the color value. + @param Width the output width of the screen section. + The images will be scaled if the output width of the screen section differs from the image section.
+ The value -1 determines that the image should not be scaled.
+ The default value is -1. + @param Width the output height of the screen section. + The images will be scaled if the output width of the screen section differs from the image section.
+ The value -1 determines that the image should not be scaled.
+ The default value is -1. + @return returns false if the rendering failed. + */ + + Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0, + int flipping = FLIP_NONE, + Common::Rect *pPartRect = NULL, + uint color = BS_ARGB(255, 255, 255, 255), + int width = -1, int height = -1); + void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); + TransparentSurface *scale(int xSize, int ySize) const; +private: + static int *scaleLine(int size, int srcSize); +}; + +/** + * A deleter for Surface objects which can be used with SharedPtr. + * + * This deleter assures Surface::free is called on deletion. + */ +/*struct SharedPtrTransparentSurfaceDeleter { + void operator()(TransparentSurface *ptr) { + ptr->free(); + delete ptr; + } +};*/ + + +} // End of namespace Graphics + + +#endif diff --git a/engines/wintermute/math/MathUtil.cpp b/engines/wintermute/math/MathUtil.cpp deleted file mode 100644 index 47b472d9cf..0000000000 --- a/engines/wintermute/math/MathUtil.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "MathUtil.h" -#include - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -float MathUtil::round(float val) { - float result = floor(val); - if (val - result >= 0.5) 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/MathUtil.h b/engines/wintermute/math/MathUtil.h deleted file mode 100644 index db814a59ac..0000000000 --- a/engines/wintermute/math/MathUtil.h +++ /dev/null @@ -1,42 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 // WINTERMUTE_MATHUTIL_H diff --git a/engines/wintermute/math/Matrix4.cpp b/engines/wintermute/math/Matrix4.cpp deleted file mode 100644 index 557f0d5c9a..0000000000 --- a/engines/wintermute/math/Matrix4.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 deleted file mode 100644 index 5def8dfe97..0000000000 --- a/engines/wintermute/math/Matrix4.h +++ /dev/null @@ -1,59 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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); - - /* union { - struct { - float _11, _12, _13, _14; - float _21, _22, _23, _24; - float _31, _32, _33, _34; - float _41, _42, _43, _44; - };*/ - float m[4][4]; - //}; - -}; - -} // end of namespace WinterMute - -#endif // WINTERMUTE_MATRIX4_H diff --git a/engines/wintermute/math/Rect32.h b/engines/wintermute/math/Rect32.h deleted file mode 100644 index e0babcbbb9..0000000000 --- a/engines/wintermute/math/Rect32.h +++ /dev/null @@ -1,86 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef WINTERMUTE_RECT32_H -#define WINTERMUTE_RECT32_H - -#include "common/system.h" - -namespace WinterMute { - -struct Point32 { - int32 x; - int32 y; -}; - -struct Rect32 { - int32 top, left; ///< The point at the top left of the rectangle (part of the rect). - int32 bottom, right; ///< The point at the bottom right of the rectangle (not part of the rect). - - Rect32() : top(0), left(0), bottom(0), right(0) {} - Rect32(int16 w, int16 h) : top(0), left(0), bottom(h), right(w) {} - Rect32(int16 x1, int16 y1, int16 x2, int16 y2) : top(y1), left(x1), bottom(y2), right(x2) { - assert(isValidRect()); - } - bool operator==(const Rect32 &rhs) const { return equals(rhs); } - bool operator!=(const Rect32 &rhs) const { return !equals(rhs); } - - int16 width() const { return right - left; } - int16 height() const { return bottom - top; } - - void setWidth(int16 aWidth) { - right = left + aWidth; - } - - void setHeight(int16 aHeight) { - bottom = top + aHeight; - } - - void setEmpty() { - left = right = top = bottom = 0; - } - - void offsetRect(int dx, int dy) { - left += dx; - top += dy; - right += dx; - bottom += dy; - } - /** - * Check if the given rect is equal to this one. - * - * @param r The rectangle to check - * - * @return true if the given rect is equal, false otherwise - */ - bool equals(const Rect32 &r) const { - return (left == r.left) && (right == r.right) && (top == r.top) && (bottom == r.bottom); - } - - bool isValidRect() const { - return (left <= right && top <= bottom); - } -}; - -} // end of namespace WinterMute - -#endif // WINTERMUTE_RECT32_H diff --git a/engines/wintermute/math/Vector2.cpp b/engines/wintermute/math/Vector2.cpp deleted file mode 100644 index 8bd10320a8..0000000000 --- a/engines/wintermute/math/Vector2.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "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 deleted file mode 100644 index 96d3a3827d..0000000000 --- a/engines/wintermute/math/Vector2.h +++ /dev/null @@ -1,75 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 // WINTERMUTE_VECTOR2_H diff --git a/engines/wintermute/math/math_util.cpp b/engines/wintermute/math/math_util.cpp new file mode 100644 index 0000000000..d9449294fb --- /dev/null +++ b/engines/wintermute/math/math_util.cpp @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/math/math_util.h" +#include + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +float MathUtil::round(float val) { + float result = floor(val); + if (val - result >= 0.5) 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 new file mode 100644 index 0000000000..db814a59ac --- /dev/null +++ b/engines/wintermute/math/math_util.h @@ -0,0 +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 // WINTERMUTE_MATHUTIL_H diff --git a/engines/wintermute/math/matrix4.cpp b/engines/wintermute/math/matrix4.cpp new file mode 100644 index 0000000000..a716e937f4 --- /dev/null +++ b/engines/wintermute/math/matrix4.cpp @@ -0,0 +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 diff --git a/engines/wintermute/math/matrix4.h b/engines/wintermute/math/matrix4.h new file mode 100644 index 0000000000..5def8dfe97 --- /dev/null +++ b/engines/wintermute/math/matrix4.h @@ -0,0 +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_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); + + /* union { + struct { + float _11, _12, _13, _14; + float _21, _22, _23, _24; + float _31, _32, _33, _34; + float _41, _42, _43, _44; + };*/ + float m[4][4]; + //}; + +}; + +} // end of namespace WinterMute + +#endif // WINTERMUTE_MATRIX4_H diff --git a/engines/wintermute/math/rect32.h b/engines/wintermute/math/rect32.h new file mode 100644 index 0000000000..e0babcbbb9 --- /dev/null +++ b/engines/wintermute/math/rect32.h @@ -0,0 +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. + * + */ + +#ifndef WINTERMUTE_RECT32_H +#define WINTERMUTE_RECT32_H + +#include "common/system.h" + +namespace WinterMute { + +struct Point32 { + int32 x; + int32 y; +}; + +struct Rect32 { + int32 top, left; ///< The point at the top left of the rectangle (part of the rect). + int32 bottom, right; ///< The point at the bottom right of the rectangle (not part of the rect). + + Rect32() : top(0), left(0), bottom(0), right(0) {} + Rect32(int16 w, int16 h) : top(0), left(0), bottom(h), right(w) {} + Rect32(int16 x1, int16 y1, int16 x2, int16 y2) : top(y1), left(x1), bottom(y2), right(x2) { + assert(isValidRect()); + } + bool operator==(const Rect32 &rhs) const { return equals(rhs); } + bool operator!=(const Rect32 &rhs) const { return !equals(rhs); } + + int16 width() const { return right - left; } + int16 height() const { return bottom - top; } + + void setWidth(int16 aWidth) { + right = left + aWidth; + } + + void setHeight(int16 aHeight) { + bottom = top + aHeight; + } + + void setEmpty() { + left = right = top = bottom = 0; + } + + void offsetRect(int dx, int dy) { + left += dx; + top += dy; + right += dx; + bottom += dy; + } + /** + * Check if the given rect is equal to this one. + * + * @param r The rectangle to check + * + * @return true if the given rect is equal, false otherwise + */ + bool equals(const Rect32 &r) const { + return (left == r.left) && (right == r.right) && (top == r.top) && (bottom == r.bottom); + } + + bool isValidRect() const { + return (left <= right && top <= bottom); + } +}; + +} // end of namespace WinterMute + +#endif // WINTERMUTE_RECT32_H diff --git a/engines/wintermute/math/vector2.cpp b/engines/wintermute/math/vector2.cpp new file mode 100644 index 0000000000..9906a59429 --- /dev/null +++ b/engines/wintermute/math/vector2.cpp @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#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 new file mode 100644 index 0000000000..96d3a3827d --- /dev/null +++ b/engines/wintermute/math/vector2.h @@ -0,0 +1,75 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_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 // WINTERMUTE_VECTOR2_H diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk index 0063d072b1..3ad30cf66b 100644 --- a/engines/wintermute/module.mk +++ b/engines/wintermute/module.mk @@ -1,119 +1,119 @@ MODULE := engines/wintermute MODULE_OBJS := \ - ad/AdActor.o \ - ad/AdEntity.o \ - ad/AdGame.o \ - ad/AdInventory.o \ - ad/AdInventoryBox.o \ - ad/AdItem.o \ - ad/AdLayer.o \ - ad/AdNodeState.o \ - ad/AdObject.o \ - ad/AdPath.o \ - ad/AdPathPoint.o \ - ad/AdRegion.o \ - ad/AdResponse.o \ - ad/AdResponseBox.o \ - ad/AdResponseContext.o \ - ad/AdRotLevel.o \ - ad/AdScaleLevel.o \ - ad/AdScene.o \ - ad/AdSceneNode.o \ - ad/AdSceneState.o \ - ad/AdSentence.o \ - ad/AdSpriteSet.o \ - ad/AdTalkDef.o \ - ad/AdTalkHolder.o \ - ad/AdTalkNode.o \ - ad/AdWaypointGroup.o \ - base/scriptables/ScEngine.o \ - base/scriptables/ScScript.o \ - base/scriptables/ScStack.o \ - base/scriptables/ScValue.o \ - base/scriptables/SXArray.o \ - base/scriptables/SXDate.o \ - base/scriptables/SXFile.o \ - base/scriptables/SXMath.o \ - base/scriptables/SxObject.o \ - base/scriptables/SXMemBuffer.o \ - base/scriptables/SXString.o \ - base/file/BDiskFile.o \ - base/file/BFile.o \ - base/file/BFileEntry.o \ - base/file/BPackage.o \ - base/file/BSaveThumbFile.o \ + ad/ad_actor.o \ + ad/ad_entity.o \ + ad/ad_game.o \ + ad/ad_inventory.o \ + ad/ad_inventory_box.o \ + ad/ad_item.o \ + ad/ad_layer.o \ + ad/ad_node_state.o \ + ad/ad_object.o \ + ad/ad_path.o \ + ad/ad_path_point.o \ + ad/ad_region.o \ + ad/ad_response.o \ + ad/ad_response_box.o \ + ad/ad_response_context.o \ + ad/ad_rot_level.o \ + ad/ad_scale_level.o \ + ad/ad_scene.o \ + ad/ad_scene_node.o \ + ad/ad_scene_state.o \ + ad/ad_sentence.o \ + ad/ad_sprite_set.o \ + ad/ad_talk_def.o \ + ad/ad_talk_holder.o \ + ad/ad_talk_node.o \ + ad/ad_waypoint_group.o \ + base/scriptables/script.o \ + base/scriptables/script_engine.o \ + base/scriptables/script_stack.o \ + base/scriptables/script_value.o \ + base/scriptables/script_ext_array.o \ + base/scriptables/script_ext_date.o \ + base/scriptables/script_ext_file.o \ + base/scriptables/script_ext_math.o \ + base/scriptables/script_ext_object.o \ + base/scriptables/script_ext_mem_buffer.o \ + base/scriptables/script_ext_string.o \ + base/file/base_disk_file.o \ + base/file/base_file.o \ + base/file/base_file_entry.o \ + base/file/base_package.o \ + base/file/base_resources.o \ + base/file/base_save_thumb_file.o \ base/file/BPkgFile.o \ - base/font/BFontBitmap.o \ - base/font/BFontTT.o \ - base/font/BFont.o \ - base/font/BFontStorage.o \ + base/font/base_font_bitmap.o \ + base/font/base_font_truetype.o \ + base/font/base_font.o \ + base/font/base_font_storage.o \ base/gfx/base_image.o \ base/gfx/base_renderer.o \ base/gfx/base_surface.o \ base/gfx/osystem/base_surface_osystem.o \ base/gfx/osystem/base_render_osystem.o \ - base/particles/PartParticle.o \ - base/particles/PartEmitter.o \ - base/particles/PartForce.o \ - base/BActiveRect.o \ - base/BBase.o \ - base/BDebugger.o \ - base/BDynBuffer.o \ - base/BFader.o \ - base/BFileManager.o \ - base/BGame.o \ - base/BFrame.o \ - base/BKeyboardState.o \ - base/BNamedObject.o \ - base/BObject.o \ - base/BParser.o \ - base/BPersistMgr.o \ - base/BPoint.o \ - base/BQuickMsg.o \ - base/BRegion.o \ - base/BRegistry.o \ - base/BResources.o \ - base/BSaveThumbHelper.o \ - base/BScriptable.o \ - base/BScriptHolder.o \ - base/BSound.o \ - base/BSoundBuffer.o \ - base/BSoundMgr.o \ - base/BSprite.o \ - base/BStringTable.o \ - base/BSubFrame.o \ - base/BSurfaceStorage.o \ - base/BTransitionMgr.o \ - base/BViewport.o \ + base/particles/part_particle.o \ + base/particles/part_emitter.o \ + base/particles/part_force.o \ + base/sound/base_sound.o \ + base/sound/base_sound_buffer.o \ + base/sound/base_sound_manager.o \ + base/base_active_rect.o \ + base/base.o \ + base/base_debugger.o \ + base/base_dynamic_buffer.o \ + base/base_fader.o \ + base/base_file_manager.o \ + base/base_game.o \ + base/base_frame.o \ + base/base_keyboard_state.o \ + base/base_named_object.o \ + base/base_object.o \ + base/base_parser.o \ + base/base_persistence_manager.o \ + base/base_point.o \ + base/base_quick_msg.o \ + base/base_region.o \ + base/base_registry.o \ + base/base_save_thumb_helper.o \ + base/base_scriptable.o \ + base/base_script_holder.o \ + base/base_sprite.o \ + base/base_string_table.o \ + base/base_sub_frame.o \ + base/base_surface_storage.o \ + base/base_transition_manager.o \ + base/base_viewport.o \ detection.o \ - graphics/transparentSurface.o \ + graphics/transparent_surface.o \ graphics/tga.o \ - math/MathUtil.o \ - math/Matrix4.o \ - math/Vector2.o \ + math/math_util.o \ + math/matrix4.o \ + math/vector2.o \ platform_osystem.o \ - system/SysClass.o \ - system/SysClassRegistry.o \ - system/SysInstance.o \ + system/sys_class.o \ + system/sys_class_registry.o \ + system/sys_instance.o \ tinyxml/tinyxml.o \ tinyxml/tinystr.o \ tinyxml/tinyxmlparser.o \ tinyxml/tinyxmlerror.o \ - ui/UIButton.o \ - ui/UIEdit.o \ - ui/UIEntity.o \ - ui/UIObject.o \ - ui/UIText.o \ - ui/UITiledImage.o \ - ui/UIWindow.o \ - utils/ConvertUTF.o \ + ui/ui_button.o \ + ui/ui_edit.o \ + ui/ui_entity.o \ + ui/ui_object.o \ + ui/ui_text.o \ + ui/ui_tiled_image.o \ + ui/ui_window.o \ + utils/convert_utf.o \ utils/crc.o \ - utils/PathUtil.o \ - utils/StringUtil.o \ + utils/path_util.o \ + utils/string_util.o \ utils/utils.o \ - video/VidPlayer.o \ - video/VidTheoraPlayer.o \ + video/video_player.o \ + video/video_theora_player.o \ video/decoders/theora_decoder.o \ wintermute.o \ persistent.o diff --git a/engines/wintermute/persistent.cpp b/engines/wintermute/persistent.cpp index 10c2132326..57997405de 100644 --- a/engines/wintermute/persistent.cpp +++ b/engines/wintermute/persistent.cpp @@ -26,67 +26,67 @@ * Copyright (c) 2011 Jan Nedoma */ -#include "engines/wintermute/ad/AdActor.h" -#include "engines/wintermute/ad/AdEntity.h" -#include "engines/wintermute/ad/AdGame.h" -#include "engines/wintermute/ad/AdInventory.h" -#include "engines/wintermute/ad/AdInventoryBox.h" -#include "engines/wintermute/ad/AdItem.h" -#include "engines/wintermute/ad/AdLayer.h" -#include "engines/wintermute/ad/AdNodeState.h" -#include "engines/wintermute/ad/AdObject.h" -#include "engines/wintermute/ad/AdPath.h" -#include "engines/wintermute/ad/AdPathPoint.h" -#include "engines/wintermute/ad/AdRegion.h" -#include "engines/wintermute/ad/AdResponse.h" -#include "engines/wintermute/ad/AdResponseBox.h" -#include "engines/wintermute/ad/AdResponseContext.h" -#include "engines/wintermute/ad/AdRotLevel.h" -#include "engines/wintermute/ad/AdScaleLevel.h" -#include "engines/wintermute/ad/AdScene.h" -#include "engines/wintermute/ad/AdSceneNode.h" -#include "engines/wintermute/ad/AdSceneState.h" -#include "engines/wintermute/ad/AdSentence.h" -#include "engines/wintermute/ad/AdSpriteSet.h" -#include "engines/wintermute/ad/AdTalkDef.h" -#include "engines/wintermute/ad/AdTalkHolder.h" -#include "engines/wintermute/ad/AdTalkNode.h" -#include "engines/wintermute/ad/AdWaypointGroup.h" -#include "engines/wintermute/base/BFader.h" -#include "engines/wintermute/base/font/BFontBitmap.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFontTT.h" -#include "engines/wintermute/base/BFrame.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BKeyboardState.h" -#include "engines/wintermute/base/BObject.h" -#include "engines/wintermute/base/BPoint.h" -#include "engines/wintermute/base/BRegion.h" -#include "engines/wintermute/base/BScriptable.h" -#include "engines/wintermute/base/BScriptHolder.h" -#include "engines/wintermute/base/BSound.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BSubFrame.h" -#include "engines/wintermute/base/BViewport.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/SXArray.h" -#include "engines/wintermute/base/scriptables/SXDate.h" -#include "engines/wintermute/base/scriptables/SXFile.h" -#include "engines/wintermute/base/scriptables/SXMath.h" -#include "engines/wintermute/base/scriptables/SXMemBuffer.h" -#include "engines/wintermute/base/scriptables/SxObject.h" -#include "engines/wintermute/base/scriptables/SXString.h" -#include "engines/wintermute/ui/UIButton.h" -#include "engines/wintermute/ui/UIEdit.h" -#include "engines/wintermute/ui/UIEntity.h" -#include "engines/wintermute/ui/UIText.h" -#include "engines/wintermute/ui/UITiledImage.h" -#include "engines/wintermute/ui/UIWindow.h" -#include "engines/wintermute/video/VidTheoraPlayer.h" -#include "engines/wintermute/system/SysClass.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_inventory.h" +#include "engines/wintermute/ad/ad_inventory_box.h" +#include "engines/wintermute/ad/ad_item.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_region.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_rot_level.h" +#include "engines/wintermute/ad/ad_scale_level.h" +#include "engines/wintermute/ad/ad_scene.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_sprite_set.h" +#include "engines/wintermute/ad/ad_talk_def.h" +#include "engines/wintermute/ad/ad_talk_holder.h" +#include "engines/wintermute/ad/ad_talk_node.h" +#include "engines/wintermute/ad/ad_waypoint_group.h" +#include "engines/wintermute/base/base_Fader.h" +#include "engines/wintermute/base/font/base_font_bitmap.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/font/base_font_truetype.h" +#include "engines/wintermute/base/base_frame.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_Keyboard_state.h" +#include "engines/wintermute/base/base_object.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_script_holder.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_sub_frame.h" +#include "engines/wintermute/base/base_viewport.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/scriptables/script_ext_array.h" +#include "engines/wintermute/base/scriptables/script_ext_date.h" +#include "engines/wintermute/base/scriptables/script_ext_file.h" +#include "engines/wintermute/base/scriptables/script_ext_math.h" +#include "engines/wintermute/base/scriptables/script_ext_mem_buffer.h" +#include "engines/wintermute/base/scriptables/script_ext_object.h" +#include "engines/wintermute/base/scriptables/script_ext_string.h" +#include "engines/wintermute/ui/ui_button.h" +#include "engines/wintermute/ui/ui_edit.h" +#include "engines/wintermute/ui/ui_entity.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/video/video_theora_player.h" +#include "engines/wintermute/system/sys_class.h" // CSysClass adds these objects to the registry, thus they aren't as leaked as they look #define REGISTER_CLASS(class_name, persistent_class)\ diff --git a/engines/wintermute/persistent.h b/engines/wintermute/persistent.h index a7d028b911..a5dac465b3 100644 --- a/engines/wintermute/persistent.h +++ b/engines/wintermute/persistent.h @@ -39,7 +39,7 @@ typedef bool(*PERSISTLOAD)(void *, CBPersistMgr *); typedef void (*SYS_INSTANCE_CALLBACK)(void *Instance, void *Data); } // end of namespace WinterMute -#include "engines/wintermute/system/SysClassRegistry.h" +#include "engines/wintermute/system/sys_class_registry.h" namespace WinterMute { diff --git a/engines/wintermute/platform_osystem.cpp b/engines/wintermute/platform_osystem.cpp index 82b53da723..2be73b7256 100644 --- a/engines/wintermute/platform_osystem.cpp +++ b/engines/wintermute/platform_osystem.cpp @@ -27,13 +27,13 @@ */ #include "engines/wintermute/dcgf.h" -#include "engines/wintermute/base/BGame.h" +#include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" -#include "engines/wintermute/utils/PathUtil.h" +#include "engines/wintermute/utils/path_util.h" #include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/BRegistry.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" +#include "engines/wintermute/base/base_registry.h" +#include "engines/wintermute/base/sound/base_sound_manager.h" +#include "engines/wintermute/base/scriptables/script_engine.h" #include "common/str.h" #include "common/textconsole.h" #include "common/system.h" diff --git a/engines/wintermute/platform_osystem.h b/engines/wintermute/platform_osystem.h index e0314898bf..50b07bccb8 100644 --- a/engines/wintermute/platform_osystem.h +++ b/engines/wintermute/platform_osystem.h @@ -30,7 +30,7 @@ #define WINTERMUTE_PLATFORMSDL_H #include "engines/wintermute/dctypes.h" -#include "engines/wintermute/math/Rect32.h" +#include "engines/wintermute/math/rect32.h" #include "engines/wintermute/wintypes.h" #include "common/events.h" diff --git a/engines/wintermute/system/SysClass.cpp b/engines/wintermute/system/SysClass.cpp deleted file mode 100644 index 2d1066ab5a..0000000000 --- a/engines/wintermute/system/SysClass.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "SysInstance.h" -#include "SysClass.h" -#include "SysClassRegistry.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BPersistMgr.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CSysClass::CSysClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistent_class) { - _name = name; - - _build = build; - _load = load; - _next = NULL; - _savedID = -1; - _persistent = persistent_class; - _numInst = 0; - - CSysClassRegistry::getInstance()->registerClass(this); -} - - -////////////////////////////////////////////////////////////////////////// -CSysClass::~CSysClass() { - CSysClassRegistry::getInstance()->unregisterClass(this); - removeAllInstances(); -} - -////////////////////////////////////////////////////////////////////////// -bool CSysClass::removeAllInstances() { - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - delete(it->_value); - } - _instances.clear(); - _instanceMap.clear(); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -CSysInstance *CSysClass::addInstance(void *instance, int id, int savedId) { - CSysInstance *inst = new CSysInstance(instance, id, this); - inst->setSavedID(savedId); - _instances[inst] = (inst); - - _instanceMap[instance] = inst; - - CSysClassRegistry::getInstance()->addInstanceToTable(inst, instance); - - return inst; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSysClass::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 CSysClass::getInstanceID(void *pointer) { - InstanceMap::iterator mapIt = _instanceMap.find(pointer); - if (mapIt == _instanceMap.end()) return -1; - else return (mapIt->_value)->getID(); -} - -////////////////////////////////////////////////////////////////////////// -void *CSysClass::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 CSysClass::getNumInstances() { - return _instances.size(); -} - -////////////////////////////////////////////////////////////////////////// -void CSysClass::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 CSysClass::saveTable(CBGame *gameRef, CBPersistMgr *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 CSysClass::loadTable(CBGame *gameRef, CBPersistMgr *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); - CSysClassRegistry::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, CSysClassRegistry::getInstance()->getNextID(), instID); - } - - } -} - -////////////////////////////////////////////////////////////////////////// -void CSysClass::saveInstances(CBGame *Game, CBPersistMgr *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 CSysClass::loadInstance(void *instance, CBPersistMgr *persistMgr) { - _load(instance, persistMgr); -} - - -////////////////////////////////////////////////////////////////////////// -void CSysClass::resetSavedIDs() { - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - (it->_value)->setSavedID(-1); - } -} - -////////////////////////////////////////////////////////////////////////// -void CSysClass::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/SysClass.h b/engines/wintermute/system/SysClass.h deleted file mode 100644 index f807ea677c..0000000000 --- a/engines/wintermute/system/SysClass.h +++ /dev/null @@ -1,130 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CSysInstance; -class CBGame; -class CBPersistMgr; -class CSysClass; - -} - -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::CSysInstance *val) const { - return (uint)((size_t)val); - } -}; - - -} - -namespace WinterMute { - -class CSysClass { -public: - CSysClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistent_class); - ~CSysClass(); - - int getNumInstances(); - bool removeInstance(void *instance); - CSysInstance *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(CBGame *Game, CBPersistMgr *PersistMgr); - void loadTable(CBGame *Game, CBPersistMgr *PersistMgr); - - void saveInstances(CBGame *Game, CBPersistMgr *PersistMgr); - void loadInstance(void *instance, CBPersistMgr *PersistMgr); - - void instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpData); - - void resetSavedIDs(); - - void dump(Common::WriteStream *stream); - -private: - int _numInst; - bool _persistent; - CSysClass *_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/SysClassRegistry.cpp b/engines/wintermute/system/SysClassRegistry.cpp deleted file mode 100644 index 3260fd3d5f..0000000000 --- a/engines/wintermute/system/SysClassRegistry.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/wintermute.h" -#include "SysInstance.h" -#include "SysClassRegistry.h" -#include "engines/wintermute/system/SysClass.h" -#include "common/stream.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CSysClassRegistry::CSysClassRegistry() { - _count = 0; - _disabled = false; -} - - -////////////////////////////////////////////////////////////////////////// -CSysClassRegistry::~CSysClassRegistry() { - unregisterClasses(); -} - -////////////////////////////////////////////////////////////////////////// -CSysClassRegistry *CSysClassRegistry::getInstance() { - return g_wintermute->getClassRegistry(); -} - -void CSysClassRegistry::unregisterClasses() { - // CSysClass calls UnregisterClass upon destruction. - while (_classes.size() > 0) { - delete _classes.begin()->_value; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CSysClassRegistry::registerClass(CSysClass *classObj) { - classObj->setID(_count++); - //_classes.insert(classObj); - _classes[classObj] = classObj; - - _nameMap[classObj->getName()] = classObj; - _idMap[classObj->getID()] = classObj; - - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSysClassRegistry::unregisterClass(CSysClass *classObj) { - - Classes::iterator it = _classes.find(classObj); - if (it == _classes.end()) return false; - - if (classObj->getNumInstances() != 0) { - char str[MAX_PATH_LENGTH]; - sprintf(str, "Memory leak@class %-20s: %d instance(s) left\n", classObj->getName().c_str(), classObj->getNumInstances()); - CBPlatform::outputDebugString(str); - } - _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 CSysClassRegistry::registerInstance(const char *className, void *instance) { - if (_disabled) return true; - - NameMap::iterator mapIt = _nameMap.find(className); - if (mapIt == _nameMap.end()) return false; - - CSysInstance *inst = (*mapIt)._value->addInstance(instance, _count++); - return (inst != NULL); -} - -////////////////////////////////////////////////////////////////////////// -void CSysClassRegistry::addInstanceToTable(CSysInstance *instance, void *pointer) { - _instanceMap[pointer] = instance; - - if (instance->getSavedID() >= 0) - _savedInstanceMap[instance->getSavedID()] = instance; -} - -////////////////////////////////////////////////////////////////////////// -int CSysClassRegistry::getNextID() { - return _count++; -} - -////////////////////////////////////////////////////////////////////////// -bool CSysClassRegistry::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 CSysClassRegistry::getPointerID(void *pointer, int *classID, int *instanceID) { - if (pointer == NULL) return true; - - InstanceMap::iterator it = _instanceMap.find(pointer); - if (it == _instanceMap.end()) return false; - - - CSysInstance *inst = (*it)._value; - *instanceID = inst->getID(); - *classID = inst->getClass()->getID(); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void *CSysClassRegistry::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, CBPersistMgr *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 CSysClassRegistry::saveTable(CBGame *gameRef, CBPersistMgr *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->_indicatorProgress = (int)(50.0f / (float)((float)_classes.size() / (float)counter)); - gameRef->displayContent(false); - gameRef->_renderer->flip(); - } - - (it->_value)->saveTable(gameRef, persistMgr); - } - persistMgr->putString(""); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CSysClassRegistry::loadTable(CBGame *gameRef, CBPersistMgr *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->_indicatorProgress = (int)(50.0f / (float)((float)numClasses / (float)i)); - gameRef->displayContentSimple(); - gameRef->_renderer->flip(); - - 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 CSysClassRegistry::saveInstances(CBGame *gameRef, CBPersistMgr *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->_indicatorProgress = (int)(50.0f + 50.0f / (float)((float)_classes.size() / (float)counter)); - gameRef->displayContent(false); - gameRef->_renderer->flip(); - } - } - gameRef->miniUpdate(); - - (it->_value)->saveInstances(gameRef, persistMgr); - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CSysClassRegistry::loadInstances(CBGame *gameRef, CBPersistMgr *persistMgr) { - // get total instances - int numInstances = persistMgr->getDWORD(); - - for (int i = 0; i < numInstances; i++) { - if (i % 20 == 0) { - gameRef->_indicatorProgress = (int)(50.0f + 50.0f / (float)((float)numInstances / (float)i)); - gameRef->displayContentSimple(); - gameRef->_renderer->flip(); - } - - 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 CSysClassRegistry::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 CSysClassRegistry::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/SysClassRegistry.h b/engines/wintermute/system/SysClassRegistry.h deleted file mode 100644 index c9c4e8c072..0000000000 --- a/engines/wintermute/system/SysClassRegistry.h +++ /dev/null @@ -1,107 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/persistent.h" -#include "engines/wintermute/system/SysClass.h" -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/func.h" -#include "common/stream.h" - -namespace WinterMute { -class CSysClass; -} - -namespace Common { -template struct Hash; -template<> struct Hash : public UnaryFunction { - uint operator()(WinterMute::CSysClass *val) const { - return (uint)((size_t)val); - } -}; - -} - -namespace WinterMute { - -class CBGame; -class CBPersistMgr; -class CSysInstance; - -class CSysClassRegistry { - void unregisterClasses(); -public: - void registerClasses(); // persistent.cpp - static CSysClassRegistry *getInstance(); - - CSysClassRegistry(); - virtual ~CSysClassRegistry(); - - bool enumInstances(SYS_INSTANCE_CALLBACK lpCallback, const char *className, void *lpData); - bool loadTable(CBGame *Game, CBPersistMgr *PersistMgr); - bool saveTable(CBGame *Game, CBPersistMgr *PersistMgr, bool quickSave); - bool loadInstances(CBGame *Game, CBPersistMgr *PersistMgr); - bool saveInstances(CBGame *Game, CBPersistMgr *PersistMgr, bool quickSave); - void *idToPointer(int classID, int instanceID); - bool getPointerID(void *pointer, int *classID, int *instanceID); - bool registerClass(CSysClass *classObj); - bool unregisterClass(CSysClass *classObj); - bool registerInstance(const char *className, void *instance); - bool unregisterInstance(const char *className, void *instance); - void dumpClasses(Common::WriteStream *stream); - int getNextID(); - void addInstanceToTable(CSysInstance *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/SysInstance.cpp b/engines/wintermute/system/SysInstance.cpp deleted file mode 100644 index b7f6079912..0000000000 --- a/engines/wintermute/system/SysInstance.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "SysInstance.h" -#include "SysClassRegistry.h" -#include "SysClass.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -CSysInstance::CSysInstance(void *instance, int id, CSysClass *sysClass) { - _instance = instance; - _id = id; - _savedID = -1; - _class = sysClass; - - _used = false; -} - -////////////////////////////////////////////////////////////////////////// -CSysInstance::~CSysInstance() { -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/system/SysInstance.h b/engines/wintermute/system/SysInstance.h deleted file mode 100644 index 6becd491af..0000000000 --- a/engines/wintermute/system/SysInstance.h +++ /dev/null @@ -1,68 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CSysClass; - -class CSysInstance { -public: - CSysInstance(void *Instance, int ID, CSysClass *sysClass); - virtual ~CSysInstance(); - - int getID() const { - return _id; - } - int getSavedID() const { - return _savedID; - } - void *getInstance() const { - return _instance; - } - CSysClass *getClass() const { - return _class; - } - - void setSavedID(int id) { - _savedID = id; - } - -private: - bool _used; - int _id; - int _savedID; - void *_instance; - CSysClass *_class; -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/system/sys_class.cpp b/engines/wintermute/system/sys_class.cpp new file mode 100644 index 0000000000..be70f8b8bd --- /dev/null +++ b/engines/wintermute/system/sys_class.cpp @@ -0,0 +1,211 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 { + +////////////////////////////////////////////////////////////////////////// +CSysClass::CSysClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistent_class) { + _name = name; + + _build = build; + _load = load; + _next = NULL; + _savedID = -1; + _persistent = persistent_class; + _numInst = 0; + + CSysClassRegistry::getInstance()->registerClass(this); +} + + +////////////////////////////////////////////////////////////////////////// +CSysClass::~CSysClass() { + CSysClassRegistry::getInstance()->unregisterClass(this); + removeAllInstances(); +} + +////////////////////////////////////////////////////////////////////////// +bool CSysClass::removeAllInstances() { + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + delete(it->_value); + } + _instances.clear(); + _instanceMap.clear(); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +CSysInstance *CSysClass::addInstance(void *instance, int id, int savedId) { + CSysInstance *inst = new CSysInstance(instance, id, this); + inst->setSavedID(savedId); + _instances[inst] = (inst); + + _instanceMap[instance] = inst; + + CSysClassRegistry::getInstance()->addInstanceToTable(inst, instance); + + return inst; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSysClass::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 CSysClass::getInstanceID(void *pointer) { + InstanceMap::iterator mapIt = _instanceMap.find(pointer); + if (mapIt == _instanceMap.end()) return -1; + else return (mapIt->_value)->getID(); +} + +////////////////////////////////////////////////////////////////////////// +void *CSysClass::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 CSysClass::getNumInstances() { + return _instances.size(); +} + +////////////////////////////////////////////////////////////////////////// +void CSysClass::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 CSysClass::saveTable(CBGame *gameRef, CBPersistMgr *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 CSysClass::loadTable(CBGame *gameRef, CBPersistMgr *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); + CSysClassRegistry::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, CSysClassRegistry::getInstance()->getNextID(), instID); + } + + } +} + +////////////////////////////////////////////////////////////////////////// +void CSysClass::saveInstances(CBGame *Game, CBPersistMgr *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 CSysClass::loadInstance(void *instance, CBPersistMgr *persistMgr) { + _load(instance, persistMgr); +} + + +////////////////////////////////////////////////////////////////////////// +void CSysClass::resetSavedIDs() { + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + (it->_value)->setSavedID(-1); + } +} + +////////////////////////////////////////////////////////////////////////// +void CSysClass::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 new file mode 100644 index 0000000000..f807ea677c --- /dev/null +++ b/engines/wintermute/system/sys_class.h @@ -0,0 +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 CSysInstance; +class CBGame; +class CBPersistMgr; +class CSysClass; + +} + +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::CSysInstance *val) const { + return (uint)((size_t)val); + } +}; + + +} + +namespace WinterMute { + +class CSysClass { +public: + CSysClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistent_class); + ~CSysClass(); + + int getNumInstances(); + bool removeInstance(void *instance); + CSysInstance *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(CBGame *Game, CBPersistMgr *PersistMgr); + void loadTable(CBGame *Game, CBPersistMgr *PersistMgr); + + void saveInstances(CBGame *Game, CBPersistMgr *PersistMgr); + void loadInstance(void *instance, CBPersistMgr *PersistMgr); + + void instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpData); + + void resetSavedIDs(); + + void dump(Common::WriteStream *stream); + +private: + int _numInst; + bool _persistent; + CSysClass *_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 new file mode 100644 index 0000000000..ce14b01385 --- /dev/null +++ b/engines/wintermute/system/sys_class_registry.cpp @@ -0,0 +1,315 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/wintermute.h" +#include "engines/wintermute/system/sys_instance.h" +#include "engines/wintermute/system/sys_class_registry.h" +#include "engines/wintermute/system/sys_class.h" +#include "common/stream.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CSysClassRegistry::CSysClassRegistry() { + _count = 0; + _disabled = false; +} + + +////////////////////////////////////////////////////////////////////////// +CSysClassRegistry::~CSysClassRegistry() { + unregisterClasses(); +} + +////////////////////////////////////////////////////////////////////////// +CSysClassRegistry *CSysClassRegistry::getInstance() { + return g_wintermute->getClassRegistry(); +} + +void CSysClassRegistry::unregisterClasses() { + // CSysClass calls UnregisterClass upon destruction. + while (_classes.size() > 0) { + delete _classes.begin()->_value; + } +} + +////////////////////////////////////////////////////////////////////////// +bool CSysClassRegistry::registerClass(CSysClass *classObj) { + classObj->setID(_count++); + //_classes.insert(classObj); + _classes[classObj] = classObj; + + _nameMap[classObj->getName()] = classObj; + _idMap[classObj->getID()] = classObj; + + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSysClassRegistry::unregisterClass(CSysClass *classObj) { + + Classes::iterator it = _classes.find(classObj); + if (it == _classes.end()) return false; + + if (classObj->getNumInstances() != 0) { + char str[MAX_PATH_LENGTH]; + sprintf(str, "Memory leak@class %-20s: %d instance(s) left\n", classObj->getName().c_str(), classObj->getNumInstances()); + CBPlatform::outputDebugString(str); + } + _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 CSysClassRegistry::registerInstance(const char *className, void *instance) { + if (_disabled) return true; + + NameMap::iterator mapIt = _nameMap.find(className); + if (mapIt == _nameMap.end()) return false; + + CSysInstance *inst = (*mapIt)._value->addInstance(instance, _count++); + return (inst != NULL); +} + +////////////////////////////////////////////////////////////////////////// +void CSysClassRegistry::addInstanceToTable(CSysInstance *instance, void *pointer) { + _instanceMap[pointer] = instance; + + if (instance->getSavedID() >= 0) + _savedInstanceMap[instance->getSavedID()] = instance; +} + +////////////////////////////////////////////////////////////////////////// +int CSysClassRegistry::getNextID() { + return _count++; +} + +////////////////////////////////////////////////////////////////////////// +bool CSysClassRegistry::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 CSysClassRegistry::getPointerID(void *pointer, int *classID, int *instanceID) { + if (pointer == NULL) return true; + + InstanceMap::iterator it = _instanceMap.find(pointer); + if (it == _instanceMap.end()) return false; + + + CSysInstance *inst = (*it)._value; + *instanceID = inst->getID(); + *classID = inst->getClass()->getID(); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +void *CSysClassRegistry::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, CBPersistMgr *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 CSysClassRegistry::saveTable(CBGame *gameRef, CBPersistMgr *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->_indicatorProgress = (int)(50.0f / (float)((float)_classes.size() / (float)counter)); + gameRef->displayContent(false); + gameRef->_renderer->flip(); + } + + (it->_value)->saveTable(gameRef, persistMgr); + } + persistMgr->putString(""); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CSysClassRegistry::loadTable(CBGame *gameRef, CBPersistMgr *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->_indicatorProgress = (int)(50.0f / (float)((float)numClasses / (float)i)); + gameRef->displayContentSimple(); + gameRef->_renderer->flip(); + + 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 CSysClassRegistry::saveInstances(CBGame *gameRef, CBPersistMgr *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->_indicatorProgress = (int)(50.0f + 50.0f / (float)((float)_classes.size() / (float)counter)); + gameRef->displayContent(false); + gameRef->_renderer->flip(); + } + } + gameRef->miniUpdate(); + + (it->_value)->saveInstances(gameRef, persistMgr); + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CSysClassRegistry::loadInstances(CBGame *gameRef, CBPersistMgr *persistMgr) { + // get total instances + int numInstances = persistMgr->getDWORD(); + + for (int i = 0; i < numInstances; i++) { + if (i % 20 == 0) { + gameRef->_indicatorProgress = (int)(50.0f + 50.0f / (float)((float)numInstances / (float)i)); + gameRef->displayContentSimple(); + gameRef->_renderer->flip(); + } + + 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 CSysClassRegistry::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 CSysClassRegistry::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 new file mode 100644 index 0000000000..e17ae9bf78 --- /dev/null +++ b/engines/wintermute/system/sys_class_registry.h @@ -0,0 +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_SYSCLASSREGISTRY_H +#define WINTERMUTE_SYSCLASSREGISTRY_H + +#include "engines/wintermute/wintypes.h" +#include "engines/wintermute/dctypes.h" +#include "engines/wintermute/persistent.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 CSysClass; +} + +namespace Common { +template struct Hash; +template<> struct Hash : public UnaryFunction { + uint operator()(WinterMute::CSysClass *val) const { + return (uint)((size_t)val); + } +}; + +} + +namespace WinterMute { + +class CBGame; +class CBPersistMgr; +class CSysInstance; + +class CSysClassRegistry { + void unregisterClasses(); +public: + void registerClasses(); // persistent.cpp + static CSysClassRegistry *getInstance(); + + CSysClassRegistry(); + virtual ~CSysClassRegistry(); + + bool enumInstances(SYS_INSTANCE_CALLBACK lpCallback, const char *className, void *lpData); + bool loadTable(CBGame *Game, CBPersistMgr *PersistMgr); + bool saveTable(CBGame *Game, CBPersistMgr *PersistMgr, bool quickSave); + bool loadInstances(CBGame *Game, CBPersistMgr *PersistMgr); + bool saveInstances(CBGame *Game, CBPersistMgr *PersistMgr, bool quickSave); + void *idToPointer(int classID, int instanceID); + bool getPointerID(void *pointer, int *classID, int *instanceID); + bool registerClass(CSysClass *classObj); + bool unregisterClass(CSysClass *classObj); + bool registerInstance(const char *className, void *instance); + bool unregisterInstance(const char *className, void *instance); + void dumpClasses(Common::WriteStream *stream); + int getNextID(); + void addInstanceToTable(CSysInstance *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 new file mode 100644 index 0000000000..c34c3cc64a --- /dev/null +++ b/engines/wintermute/system/sys_instance.cpp @@ -0,0 +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 { + +////////////////////////////////////////////////////////////////////////// +CSysInstance::CSysInstance(void *instance, int id, CSysClass *sysClass) { + _instance = instance; + _id = id; + _savedID = -1; + _class = sysClass; + + _used = false; +} + +////////////////////////////////////////////////////////////////////////// +CSysInstance::~CSysInstance() { +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/system/sys_instance.h b/engines/wintermute/system/sys_instance.h new file mode 100644 index 0000000000..6becd491af --- /dev/null +++ b/engines/wintermute/system/sys_instance.h @@ -0,0 +1,68 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_SYSINSTANCE_H +#define WINTERMUTE_SYSINSTANCE_H + +namespace WinterMute { + +class CSysClass; + +class CSysInstance { +public: + CSysInstance(void *Instance, int ID, CSysClass *sysClass); + virtual ~CSysInstance(); + + int getID() const { + return _id; + } + int getSavedID() const { + return _savedID; + } + void *getInstance() const { + return _instance; + } + CSysClass *getClass() const { + return _class; + } + + void setSavedID(int id) { + _savedID = id; + } + +private: + bool _used; + int _id; + int _savedID; + void *_instance; + CSysClass *_class; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/ui/UIButton.cpp b/engines/wintermute/ui/UIButton.cpp deleted file mode 100644 index 273f923376..0000000000 --- a/engines/wintermute/ui/UIButton.cpp +++ /dev/null @@ -1,1046 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BDynBuffer.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/ui/UIButton.h" -#include "engines/wintermute/ui/UITiledImage.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BActiveRect.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CUIButton, false) - -////////////////////////////////////////////////////////////////////////// -CUIButton::CUIButton(CBGame *inGame): CUIObject(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; -} - - -////////////////////////////////////////////////////////////////////////// -CUIButton::~CUIButton() { - 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 CUIButton::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CUIButton::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CUIButton::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; - CBParser parser(_gameRef); - - 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 CUITiledImage(_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 CUITiledImage(_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 CUITiledImage(_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 CUITiledImage(_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 CUITiledImage(_gameRef); - if (!_backFocus || DID_FAIL(_backFocus->loadFile((char *)params))) { - delete _backFocus; - _backFocus = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CUIButton::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "BUTTON\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->_filename) - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); - if (_backHover && _backHover->_filename) - buffer->putTextIndent(indent + 2, "BACK_HOVER=\"%s\"\n", _backHover->_filename); - if (_backPress && _backPress->_filename) - buffer->putTextIndent(indent + 2, "BACK_PRESS=\"%s\"\n", _backPress->_filename); - if (_backDisable && _backDisable->_filename) - buffer->putTextIndent(indent + 2, "BACK_DISABLE=\"%s\"\n", _backDisable->_filename); - if (_backFocus && _backFocus->_filename) - buffer->putTextIndent(indent + 2, "BACK_FOCUS=\"%s\"\n", _backFocus->_filename); - - if (_image && _image->_filename) - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); - if (_imageHover && _imageHover->_filename) - buffer->putTextIndent(indent + 2, "IMAGE_HOVER=\"%s\"\n", _imageHover->_filename); - if (_imagePress && _imagePress->_filename) - buffer->putTextIndent(indent + 2, "IMAGE_PRESS=\"%s\"\n", _imagePress->_filename); - if (_imageDisable && _imageDisable->_filename) - buffer->putTextIndent(indent + 2, "IMAGE_DISABLE=\"%s\"\n", _imageDisable->_filename); - if (_imageFocus && _imageFocus->_filename) - buffer->putTextIndent(indent + 2, "IMAGE_FOCUS=\"%s\"\n", _imageFocus->_filename); - - if (_font && _font->_filename) - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); - if (_fontHover && _fontHover->_filename) - buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->_filename); - if (_fontPress && _fontPress->_filename) - buffer->putTextIndent(indent + 2, "FONT_PRESS=\"%s\"\n", _fontPress->_filename); - if (_fontDisable && _fontDisable->_filename) - buffer->putTextIndent(indent + 2, "FONT_DISABLE=\"%s\"\n", _fontDisable->_filename); - if (_fontFocus && _fontFocus->_filename) - buffer->putTextIndent(indent + 2, "FONT_FOCUS=\"%s\"\n", _fontFocus->_filename); - - if (_cursor && _cursor->_filename) - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); - - - 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("CUIButton::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 (int i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CUIButton::correctSize() { - Rect32 rect; - - CBSprite *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 CUIButton::display(int offsetX, int offsetY) { - if (!_visible) - return STATUS_OK; - - CUITiledImage *back = NULL; - CBSprite *image = NULL; - CBFont *font = 0; - - //RECT rect; - //CBPlatform::setRect(&rect, OffsetX + _posX, OffsetY + _posY, OffsetX+_posX+_width, OffsetY+_posY+_height); - //_hover = (!_disable && CBPlatform::ptInRect(&rect, _gameRef->_mousePos)!=FALSE); - _hover = (!_disable && _gameRef->_activeObject == this && (_gameRef->_interactive || _gameRef->_state == GAME_SEMI_FROZEN)); - - if ((_press && _hover && !_gameRef->_mouseLeftDown) || - (_oneTimePress && CBPlatform::getTime() - _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->_rectList.add(new CBActiveRect(_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 CUIButton::press() { - applyEvent("Press"); - if (_listenerObject) _listenerObject->listen(_listenerParamObject, _listenerParamDWORD); - if (_parentNotify && _parent) _parent->applyEvent(_name); - - _oneTimePress = false; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CUIButton::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetDisabledFont - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetDisabledFont") == 0) { - stack->correctParams(1); - CScValue *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); - CScValue *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); - CScValue *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); - CScValue *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 CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_imageDisable->_filename); - - 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 CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_imageHover->_filename); - - 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 CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_imagePress->_filename); - - 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 CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_imageFocus->_filename); - - 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 = CBPlatform::getTime(); - } - stack->pushNULL(); - - return STATUS_OK; - } - - - else return CUIObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CUIButton::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 CUIObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIButton::scSetProperty(const char *name, CScValue *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 CUIObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CUIButton::scToString() { - return "[button]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIButton::persist(CBPersistMgr *persistMgr) { - - CUIObject::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->_saving) { - _oneTimePress = false; - _oneTimePressTime = 0; - } - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ui/UIButton.h b/engines/wintermute/ui/UIButton.h deleted file mode 100644 index 5bdc075ebc..0000000000 --- a/engines/wintermute/ui/UIButton.h +++ /dev/null @@ -1,79 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 "UIObject.h" -#include "engines/wintermute/dctypes.h" // Added by ClassView - -namespace WinterMute { - -class CUIButton : public CUIObject { -public: - bool _pixelPerfect; - bool _stayPressed; - bool _centerImage; - bool _oneTimePress; - uint32 _oneTimePressTime; - DECLARE_PERSISTENT(CUIButton, CUIObject) - void press(); - virtual bool display(int offsetX = 0, int offsetY = 0); - bool _press; - bool _hover; - void correctSize(); - TTextAlign _align; - CBSprite *_imageHover; - CBSprite *_imagePress; - CBSprite *_imageDisable; - CBSprite *_imageFocus; - CBFont *_fontDisable; - CBFont *_fontPress; - CBFont *_fontHover; - CBFont *_fontFocus; - CUITiledImage *_backPress; - CUITiledImage *_backHover; - CUITiledImage *_backDisable; - CUITiledImage *_backFocus; - CUIButton(CBGame *inGame = NULL); - virtual ~CUIButton(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ui/UIEdit.cpp b/engines/wintermute/ui/UIEdit.cpp deleted file mode 100644 index 610853d8cb..0000000000 --- a/engines/wintermute/ui/UIEdit.cpp +++ /dev/null @@ -1,857 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/UIEdit.h" -#include "engines/wintermute/ui/UIObject.h" -#include "engines/wintermute/ui/UITiledImage.h" -#include "engines/wintermute/utils/StringUtil.h" -#include "engines/wintermute/base/BActiveRect.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/BKeyboardState.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/utils/utils.h" -#include "common/util.h" -#include "common/keyboard.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CUIEdit, false) - -////////////////////////////////////////////////////////////////////////// -CUIEdit::CUIEdit(CBGame *inGame): CUIObject(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; -} - - -////////////////////////////////////////////////////////////////////////// -CUIEdit::~CUIEdit() { - if (!_sharedFonts) { - if (_fontSelected) _gameRef->_fontStorage->removeFont(_fontSelected); - } - - delete[] _cursorChar; - _cursorChar = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIEdit::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CUIEdit::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CUIEdit::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; - CBParser parser(_gameRef); - - 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 CUITiledImage(_gameRef); - if (!_back || DID_FAIL(_back->loadFile((char *)params))) { - delete _back; - _back = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new CBSprite(_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 CBSprite(_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 CUIEdit::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "EDIT\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->_filename) - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); - - if (_image && _image->_filename) - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); - - if (_font && _font->_filename) - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); - if (_fontSelected && _fontSelected->_filename) - buffer->putTextIndent(indent + 2, "FONT_SELECTED=\"%s\"\n", _fontSelected->_filename); - - if (_cursor && _cursor->_filename) - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); - - 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 (int i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CUIEdit::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CUIObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CUIEdit::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 CUIObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIEdit::scSetProperty(const char *name, CScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // SelStart - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SelStart") == 0) { - _selStart = value->getInt(); - _selStart = MAX(_selStart, 0); - _selStart = MIN((size_t)_selStart, strlen(_text)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SelEnd - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SelEnd") == 0) { - _selEnd = value->getInt(); - _selEnd = MAX(_selEnd, 0); - _selEnd = MIN((size_t)_selEnd, strlen(_text)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorBlinkRate - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorBlinkRate") == 0) { - _cursorBlinkRate = 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 CUIObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CUIEdit::scToString() { - return "[edit]"; -} - - -////////////////////////////////////////////////////////////////////////// -void CUIEdit::setCursorChar(const char *character) { - if (!character) return; - delete[] _cursorChar; - _cursorChar = new char [strlen(character) + 1]; - if (_cursorChar) strcpy(_cursorChar, character); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIEdit::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 - CBFont *font; - CBFont *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 = MIN((size_t)_selStart, strlen(_text)); - _selEnd = 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 (CBPlatform::getTime() - _lastBlinkTime >= _cursorBlinkRate) { - _lastBlinkTime = CBPlatform::getTime(); - _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 (CBPlatform::getTime() - _lastBlinkTime >= _cursorBlinkRate) { - _lastBlinkTime = CBPlatform::getTime(); - _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->_rectList.add(new CBActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); - - - _gameRef->_textEncoding = OrigEncoding; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIEdit::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 (CBKeyboardState::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 (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; - handled = true; - break; - - case Common::KEYCODE_RIGHT: - case Common::KEYCODE_DOWN: - _selEnd++; - if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; - handled = true; - break; - - case Common::KEYCODE_HOME: - if (_gameRef->_textRTL) { - _selEnd = strlen(_text); - if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; - } else { - _selEnd = 0; - if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; - } - handled = true; - break; - - case Common::KEYCODE_END: - if (_gameRef->_textRTL) { - _selEnd = 0; - if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; - } else { - _selEnd = strlen(_text); - if (!CBKeyboardState::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, (byte *)StringUtil::wideToAnsi(wstr).c_str(), 1); - - if (_gameRef->_textRTL) _selEnd = _selStart; - else _selStart = _selEnd; - - return true; - } - - return false; -} - - - -////////////////////////////////////////////////////////////////////////// -int CUIEdit::deleteChars(int start, int end) { - if (start > end) CBUtils::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(_name); - - return end - start; -} - - -////////////////////////////////////////////////////////////////////////// -int CUIEdit::insertChars(int pos, 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(_name); - - return num; -} - - - -////////////////////////////////////////////////////////////////////////// -bool CUIEdit::persist(CBPersistMgr *persistMgr) { - - CUIObject::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->_saving) { - _cursorVisible = false; - _lastBlinkTime = 0; - } - - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ui/UIEdit.h b/engines/wintermute/ui/UIEdit.h deleted file mode 100644 index 7249301592..0000000000 --- a/engines/wintermute/ui/UIEdit.h +++ /dev/null @@ -1,72 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 "UIObject.h" -#include "common/events.h" - -namespace WinterMute { -class CBFont; -class CUIEdit : public CUIObject { -public: - DECLARE_PERSISTENT(CUIEdit, CUIObject) - int _maxLength; - int insertChars(int pos, 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; - CBFont *_fontSelected; - CUIEdit(CBGame *inGame); - virtual ~CUIEdit(); - - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ui/UIEntity.cpp b/engines/wintermute/ui/UIEntity.cpp deleted file mode 100644 index 7fbd2d13ff..0000000000 --- a/engines/wintermute/ui/UIEntity.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/AdEntity.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/ui/UIEntity.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CUIEntity, false) - -////////////////////////////////////////////////////////////////////////// -CUIEntity::CUIEntity(CBGame *inGame): CUIObject(inGame) { - _type = UI_CUSTOM; - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -CUIEntity::~CUIEntity() { - if (_entity) _gameRef->unregisterObject(_entity); - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIEntity::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CUIEntity::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CUIEntity::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; - CBParser parser(_gameRef); - - 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 CUIEntity::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "ENTITY_CONTAINER\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - - 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->_filename) - buffer->putTextIndent(indent + 2, "ENTITY=\"%s\"\n", _entity->_filename); - - buffer->putTextIndent(indent + 2, "\n"); - - // scripts - for (int i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CUIEntity::setEntity(const char *filename) { - if (_entity) _gameRef->unregisterObject(_entity); - _entity = new CAdEntity(_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 CUIEntity::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 CUIEntity::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CUIObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CUIEntity::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 CUIObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIEntity::scSetProperty(const char *name, CScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Freezable - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Freezable") == 0) { - if (_entity) _entity->makeFreezable(value->getBool()); - return STATUS_OK; - } else return CUIObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CUIEntity::scToString() { - return "[entity container]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIEntity::persist(CBPersistMgr *persistMgr) { - - CUIObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_entity)); - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ui/UIEntity.h b/engines/wintermute/ui/UIEntity.h deleted file mode 100644 index b0711838a5..0000000000 --- a/engines/wintermute/ui/UIEntity.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 "UIObject.h" - -namespace WinterMute { -class CAdEntity; -class CUIEntity : public CUIObject { -public: - DECLARE_PERSISTENT(CUIEntity, CUIObject) - CUIEntity(CBGame *inGame); - virtual ~CUIEntity(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - virtual bool display(int offsetX = 0, int offsetY = 0); - CAdEntity *_entity; - bool setEntity(const char *filename); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ui/UIObject.cpp b/engines/wintermute/ui/UIObject.cpp deleted file mode 100644 index 8b3dc19537..0000000000 --- a/engines/wintermute/ui/UIObject.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BGame.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/ui/UIObject.h" -#include "engines/wintermute/ui/UITiledImage.h" -#include "engines/wintermute/ui/UIWindow.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/font/BFontStorage.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CUIObject, false) - -////////////////////////////////////////////////////////////////////////// -CUIObject::CUIObject(CBGame *inGame): CBObject(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; -} - - -////////////////////////////////////////////////////////////////////////// -CUIObject::~CUIObject() { - if (!_gameRef->_loadInProgress) CSysClassRegistry::getInstance()->enumInstances(CBGame::invalidateValues, "CScValue", (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 CUIObject::setText(const char *text) { - if (_text) delete [] _text; - _text = new char [strlen(text) + 1]; - if (_text) { - strcpy(_text, text); - for (int i = 0; i < strlen(_text); i++) { - if (_text[i] == '|') _text[i] = '\n'; - } - } -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIObject::display(int offsetX, int offsetY) { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CUIObject::setListener(CBScriptHolder *object, CBScriptHolder *listenerObject, uint32 listenerParam) { - _listenerObject = object; - _listenerParamObject = listenerObject; - _listenerParamDWORD = listenerParam; -} - - -////////////////////////////////////////////////////////////////////////// -void CUIObject::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 CUIObject::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetFont - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetFont") == 0) { - stack->correctParams(1); - CScValue *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); - CScValue *val = stack->pop(); - - /* const char *filename = */ val->getString(); - - delete _image; - _image = NULL; - if (val->isNULL()) { - stack->pushBool(true); - return STATUS_OK; - } - - _image = new CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_image->_filename); - - 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) { - CUIWindow *win = (CUIWindow *)_parent; - - int i; - bool found = false; - CScValue *val = stack->pop(); - // find directly - if (val->isNative()) { - CUIObject *widget = (CUIObject *)val->getNative(); - for (i = 0; i < win->_widgets.getSize(); i++) { - if (win->_widgets[i] == widget) { - found = true; - break; - } - } - } - // find by name - else { - const char *findName = val->getString(); - for (i = 0; i < win->_widgets.getSize(); i++) { - if (scumm_stricmp(win->_widgets[i]->_name, findName) == 0) { - found = true; - break; - } - } - } - - if (found) { - bool done = false; - for (int j = 0; j < win->_widgets.getSize(); j++) { - if (win->_widgets[j] == this) { - if (strcmp(name, "MoveAfter") == 0) i++; - if (j >= i) j++; - - win->_widgets.insertAt(i, this); - win->_widgets.removeAt(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) { - CUIWindow *win = (CUIWindow *)_parent; - for (int i = 0; i < win->_widgets.getSize(); i++) { - if (win->_widgets[i] == this) { - win->_widgets.removeAt(i); - win->_widgets.insertAt(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) { - CUIWindow *win = (CUIWindow *)_parent; - for (int i = 0; i < win->_widgets.getSize(); i++) { - if (win->_widgets[i] == this) { - win->_widgets.removeAt(i); - win->_widgets.add(this); - break; - } - } - stack->pushBool(true); - } else stack->pushBool(false); - - return STATUS_OK; - } - - else return CBObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CUIObject::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(_name); - 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) { - CUIWindow *win = (CUIWindow *)_parent; - for (int i = 0; i < win->_widgets.getSize(); i++) { - if (win->_widgets[i] == this) { - if (strcmp(name, "NextSibling") == 0) { - if (i < win->_widgets.getSize() - 1) _scValue->setNative(win->_widgets[i + 1], true); - } else { - if (i > 0) _scValue->setNative(win->_widgets[i - 1], true); - } - break; - } - } - } - return _scValue; - } - - else return CBObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIObject::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CUIObject::scToString() { - return "[ui_object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIObject::isFocused() { - if (!_gameRef->_focusedWindow) return false; - if (_gameRef->_focusedWindow == this) return true; - - CUIObject *obj = _gameRef->_focusedWindow; - while (obj) { - if (obj == this) return true; - else obj = obj->_focusedWidget; - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIObject::handleMouse(TMouseEvent event, TMouseButton button) { - // handle focus change - if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { - focus(); - } - return CBObject::handleMouse(event, button); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIObject::focus() { - CUIObject *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((CUIWindow *)obj); - } - - obj = obj->_parent; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIObject::getTotalOffset(int *offsetX, int *offsetY) { - int offX = 0, offY = 0; - - CUIObject *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 CUIObject::persist(CBPersistMgr *persistMgr) { - - CBObject::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 CUIObject::saveAsText(CBDynBuffer *buffer, int indent) { - return STATUS_FAILED; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/ui/UIObject.h b/engines/wintermute/ui/UIObject.h deleted file mode 100644 index 26eecefe89..0000000000 --- a/engines/wintermute/ui/UIObject.h +++ /dev/null @@ -1,83 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/BObject.h" -#include "engines/wintermute/dctypes.h" // Added by ClassView - -namespace WinterMute { - -class CUITiledImage; -class CBFont; -class CUIObject : public CBObject { -public: - - bool getTotalOffset(int *offsetX, int *offsetY); - bool _canFocus; - bool focus(); - virtual bool handleMouse(TMouseEvent event, TMouseButton button); - bool isFocused(); - bool _parentNotify; - DECLARE_PERSISTENT(CUIObject, CBObject) - CUIObject *_parent; - virtual bool display(int offsetX = 0, int offsetY = 0); - virtual void correctSize(); - bool _sharedFonts; - bool _sharedImages; - void setText(const char *text); - char *_text; - CBFont *_font; - bool _visible; - CUITiledImage *_back; - bool _disable; - CUIObject(CBGame *inGame = NULL); - virtual ~CUIObject(); - int _width; - int _height; - TUIObjectType _type; - CBSprite *_image; - void setListener(CBScriptHolder *object, CBScriptHolder *listenerObject, uint32 listenerParam); - CBScriptHolder *_listenerParamObject; - uint32 _listenerParamDWORD; - CBScriptHolder *_listenerObject; - CUIObject *_focusedWidget; - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ui/UIText.cpp b/engines/wintermute/ui/UIText.cpp deleted file mode 100644 index a496483f67..0000000000 --- a/engines/wintermute/ui/UIText.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/BDynBuffer.h" -#include "engines/wintermute/ui/UIText.h" -#include "engines/wintermute/ui/UITiledImage.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CUIText, false) - -////////////////////////////////////////////////////////////////////////// -CUIText::CUIText(CBGame *inGame): CUIObject(inGame) { - _textAlign = TAL_LEFT; - _verticalAlign = VAL_CENTER; - _type = UI_STATIC; - _canFocus = false; -} - - -////////////////////////////////////////////////////////////////////////// -CUIText::~CUIText() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIText::display(int offsetX, int offsetY) { - if (!_visible) return STATUS_OK; - - - CBFont *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 CBActiveRect(_gameRef, this, NULL, OffsetX + _posX, OffsetY + _posY, _width, _height, 100, 100, false)); - - return STATUS_OK; -} - - - -////////////////////////////////////////////////////////////////////////// -bool CUIText::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CUIText::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CUIText::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; - CBParser parser(_gameRef); - - 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 CUITiledImage(_gameRef); - if (!_back || DID_FAIL(_back->loadFile((char *)params))) { - delete _back; - _back = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new CBSprite(_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 CBSprite(_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 CUIText::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "STATIC\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->_filename) - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); - - if (_image && _image->_filename) - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); - - if (_font && _font->_filename) - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); - - if (_cursor && _cursor->_filename) - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); - - 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("CUIText::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 (int i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CUIText::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CUIObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CUIText::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 CUIObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIText::scSetProperty(const char *name, CScValue *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 CUIObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CUIText::scToString() { - return "[static]"; -} - - - -////////////////////////////////////////////////////////////////////////// -bool CUIText::persist(CBPersistMgr *persistMgr) { - - CUIObject::persist(persistMgr); - persistMgr->transfer(TMEMBER_INT(_textAlign)); - persistMgr->transfer(TMEMBER_INT(_verticalAlign)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIText::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/UIText.h b/engines/wintermute/ui/UIText.h deleted file mode 100644 index 62fbf00b0a..0000000000 --- a/engines/wintermute/ui/UIText.h +++ /dev/null @@ -1,60 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 "UIObject.h" - -namespace WinterMute { - -class CUIText : public CUIObject { -private: - bool sizeToFit(); -public: - virtual bool display(int offsetX, int offsetY); - DECLARE_PERSISTENT(CUIText, CUIObject) - CUIText(CBGame *inGame = NULL); - virtual ~CUIText(); - TTextAlign _textAlign; - TVerticalAlign _verticalAlign; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ui/UITiledImage.cpp b/engines/wintermute/ui/UITiledImage.cpp deleted file mode 100644 index 04a2cfca58..0000000000 --- a/engines/wintermute/ui/UITiledImage.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ui/UITiledImage.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BSubFrame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CUITiledImage, false) - -////////////////////////////////////////////////////////////////////////// -CUITiledImage::CUITiledImage(CBGame *inGame): CBObject(inGame) { - _image = NULL; - - CBPlatform::setRectEmpty(&_upLeft); - CBPlatform::setRectEmpty(&_upMiddle); - CBPlatform::setRectEmpty(&_upRight); - CBPlatform::setRectEmpty(&_middleLeft); - CBPlatform::setRectEmpty(&_middleMiddle); - CBPlatform::setRectEmpty(&_middleRight); - CBPlatform::setRectEmpty(&_downLeft); - CBPlatform::setRectEmpty(&_downMiddle); - CBPlatform::setRectEmpty(&_downRight); -} - - -////////////////////////////////////////////////////////////////////////// -CUITiledImage::~CUITiledImage() { - delete _image; - _image = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUITiledImage::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 CUITiledImage::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CUITiledImage::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CUITiledImage::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; - CBParser parser(_gameRef); - 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 CBSubFrame(_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 - CBPlatform::setRect(&_upLeft, 0, 0, h1, v1); - CBPlatform::setRect(&_upMiddle, h1, 0, h1 + h2, v1); - CBPlatform::setRect(&_upRight, h1 + h2, 0, h1 + h2 + h3, v1); - - // middle row - CBPlatform::setRect(&_middleLeft, 0, v1, h1, v1 + v2); - CBPlatform::setRect(&_middleMiddle, h1, v1, h1 + h2, v1 + v2); - CBPlatform::setRect(&_middleRight, h1 + h2, v1, h1 + h2 + h3, v1 + v2); - - // down row - CBPlatform::setRect(&_downLeft, 0, v1 + v2, h1, v1 + v2 + v3); - CBPlatform::setRect(&_downMiddle, h1, v1 + v2, h1 + h2, v1 + v2 + v3); - CBPlatform::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 (CBPlatform::isRectEmpty(&_upLeft)) CBPlatform::setRect(&_upLeft, 0, 0, width, height); - if (CBPlatform::isRectEmpty(&_upMiddle)) CBPlatform::setRect(&_upMiddle, width, 0, 2 * width, height); - if (CBPlatform::isRectEmpty(&_upRight)) CBPlatform::setRect(&_upRight, 2 * width, 0, 3 * width, height); - - if (CBPlatform::isRectEmpty(&_middleLeft)) CBPlatform::setRect(&_middleLeft, 0, height, width, 2 * height); - if (CBPlatform::isRectEmpty(&_middleMiddle)) CBPlatform::setRect(&_middleMiddle, width, height, 2 * width, 2 * height); - if (CBPlatform::isRectEmpty(&_middleRight)) CBPlatform::setRect(&_middleRight, 2 * width, height, 3 * width, 2 * height); - - if (CBPlatform::isRectEmpty(&_downLeft)) CBPlatform::setRect(&_downLeft, 0, 2 * height, width, 3 * height); - if (CBPlatform::isRectEmpty(&_downMiddle)) CBPlatform::setRect(&_downMiddle, width, 2 * height, 2 * width, 3 * height); - if (CBPlatform::isRectEmpty(&_downRight)) CBPlatform::setRect(&_downRight, 2 * width, 2 * height, 3 * width, 3 * height); - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CUITiledImage::saveAsText(CBDynBuffer *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 - CBBase::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void CUITiledImage::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 CUITiledImage::persist(CBPersistMgr *persistMgr) { - CBObject::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/UITiledImage.h b/engines/wintermute/ui/UITiledImage.h deleted file mode 100644 index 379af85e81..0000000000 --- a/engines/wintermute/ui/UITiledImage.h +++ /dev/null @@ -1,63 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 "UIObject.h" -#include "common/rect.h" - -namespace WinterMute { -class CBSubFrame; -class CUITiledImage : public CBObject { -public: - DECLARE_PERSISTENT(CUITiledImage, CBObject) - void correctSize(int *width, int *height); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - bool display(int x, int y, int width, int height); - CUITiledImage(CBGame *inGame = NULL); - virtual ~CUITiledImage(); - CBSubFrame *_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/UIWindow.cpp b/engines/wintermute/ui/UIWindow.cpp deleted file mode 100644 index 35330e720e..0000000000 --- a/engines/wintermute/ui/UIWindow.cpp +++ /dev/null @@ -1,1327 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/ui/UIWindow.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BParser.h" -#include "engines/wintermute/base/BActiveRect.h" -#include "engines/wintermute/base/BDynBuffer.h" -#include "engines/wintermute/base/BKeyboardState.h" -#include "engines/wintermute/base/scriptables/ScValue.h" -#include "engines/wintermute/ui/UIButton.h" -#include "engines/wintermute/ui/UIEdit.h" -#include "engines/wintermute/ui/UIText.h" -#include "engines/wintermute/ui/UITiledImage.h" -#include "engines/wintermute/base/BViewport.h" -#include "engines/wintermute/base/font/BFontStorage.h" -#include "engines/wintermute/base/font/BFont.h" -#include "engines/wintermute/base/BStringTable.h" -#include "engines/wintermute/base/scriptables/ScScript.h" -#include "engines/wintermute/base/scriptables/ScStack.h" -#include "engines/wintermute/base/BSprite.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/platform_osystem.h" - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CUIWindow, false) - -////////////////////////////////////////////////////////////////////////// -CUIWindow::CUIWindow(CBGame *inGame): CUIObject(inGame) { - CBPlatform::setRectEmpty(&_titleRect); - CBPlatform::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; -} - - -////////////////////////////////////////////////////////////////////////// -CUIWindow::~CUIWindow() { - close(); - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void CUIWindow::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 (int i = 0; i < _widgets.getSize(); i++) delete _widgets[i]; - _widgets.removeAll(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::display(int offsetX, int offsetY) { - // go exclusive - if (_mode == WINDOW_EXCLUSIVE || _mode == WINDOW_SYSTEM_EXCLUSIVE) { - if (!_shieldWindow) _shieldWindow = new CUIWindow(_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 CUIButton(_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) _gameRef->_renderer->fadeToColor(_fadeColor); - - 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 CBViewport(_gameRef); - if (_viewport) { - _viewport->setRect(_posX + offsetX, _posY + offsetY, _posX + _width + offsetX, _posY + _height + offsetY); - _gameRef->pushViewport(_viewport); - popViewport = true; - } - } - - - CUITiledImage *back = _back; - CBSprite *image = _image; - CBFont *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 (!CBPlatform::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->_rectList.add(new CBActiveRect(_gameRef, this, NULL, _posX + offsetX, _posY + offsetY, _width, _height, 100, 100, false)); - - for (int i = 0; i < _widgets.getSize(); i++) { - _widgets[i]->display(_posX + offsetX, _posY + offsetY); - } - - if (_alphaColor != 0) - _gameRef->_renderer->_forceAlphaColor = 0; - - if (popViewport) - _gameRef->popViewport(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::loadFile(const char *filename) { - byte *buffer = _gameRef->_fileManager->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "CUIWindow::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - _filename = new char [strlen(filename) + 1]; - strcpy(_filename, 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 CUIWindow::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; - CBParser parser(_gameRef); - - 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 CUITiledImage(_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 CUITiledImage(_gameRef); - if (!_backInactive || DID_FAIL(_backInactive->loadFile((char *)params))) { - delete _backInactive; - _backInactive = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new CBSprite(_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 CBSprite(_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 CBSprite(_gameRef); - if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { - delete _cursor; - _cursor = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_BUTTON: { - CUIButton *btn = new CUIButton(_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: { - CUIText *text = new CUIText(_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: { - CUIEdit *edit = new CUIEdit(_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: { - CUIWindow *win = new CUIWindow(_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 CUIWindow::saveAsText(CBDynBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "WINDOW\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->_filename) - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); - if (_backInactive && _backInactive->_filename) - buffer->putTextIndent(indent + 2, "BACK_INACTIVE=\"%s\"\n", _backInactive->_filename); - - if (_image && _image->_filename) - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); - if (_imageInactive && _imageInactive->_filename) - buffer->putTextIndent(indent + 2, "IMAGE_INACTIVE=\"%s\"\n", _imageInactive->_filename); - - if (_font && _font->_filename) - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); - if (_fontInactive && _fontInactive->_filename) - buffer->putTextIndent(indent + 2, "FONT_INACTIVE=\"%s\"\n", _fontInactive->_filename); - - if (_cursor && _cursor->_filename) - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); - - 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 (!CBPlatform::isRectEmpty(&_titleRect)) { - buffer->putTextIndent(indent + 2, "TITLE_RECT { %d, %d, %d, %d }\n", _titleRect.left, _titleRect.top, _titleRect.right, _titleRect.bottom); - } - - if (!CBPlatform::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 (int i = 0; i < _scripts.getSize(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - CBBase::saveAsText(buffer, indent + 2); - - // controls - for (int i = 0; i < _widgets.getSize(); i++) - _widgets[i]->saveAsText(buffer, indent + 2); - - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::enableWidget(const char *name, bool Enable) { - for (int i = 0; i < _widgets.getSize(); i++) { - if (scumm_stricmp(_widgets[i]->_name, name) == 0) _widgets[i]->_disable = !Enable; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::showWidget(const char *name, bool Visible) { - for (int i = 0; i < _widgets.getSize(); i++) { - if (scumm_stricmp(_widgets[i]->_name, name) == 0) _widgets[i]->_visible = Visible; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // GetWidget / GetControl - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GetWidget") == 0 || strcmp(name, "GetControl") == 0) { - stack->correctParams(1); - CScValue *val = stack->pop(); - if (val->getType() == VAL_INT) { - int widget = val->getInt(); - if (widget < 0 || widget >= _widgets.getSize()) stack->pushNULL(); - else stack->pushNative(_widgets[widget], true); - } else { - for (int i = 0; i < _widgets.getSize(); i++) { - if (scumm_stricmp(_widgets[i]->_name, 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 CBSprite(_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->_filename) stack->pushNULL(); - else stack->pushString(_imageInactive->_filename); - - 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); - - CScValue *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); - CScValue *val = stack->pop(); - - CUIButton *btn = new CUIButton(_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); - CScValue *val = stack->pop(); - - CUIText *sta = new CUIText(_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); - CScValue *val = stack->pop(); - - CUIEdit *edi = new CUIEdit(_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); - CScValue *val = stack->pop(); - - CUIWindow *win = new CUIWindow(_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); - CScValue *val = stack->pop(); - CUIObject *obj = (CUIObject *)val->getNative(); - - for (int i = 0; i < _widgets.getSize(); i++) { - if (_widgets[i] == obj) { - delete _widgets[i]; - _widgets.removeAt(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 CUIObject::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -CScValue *CUIWindow::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.getSize()); - 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 CUIObject::scGetProperty(name); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::scSetProperty(const char *name, CScValue *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 CUIObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *CUIWindow::scToString() { - return "[window]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::handleKeypress(Common::Event *event, bool printable) { -//TODO - if (event->type == Common::EVENT_KEYDOWN && event->kbd.keycode == Common::KEYCODE_TAB) { - return DID_SUCCEED(moveFocus(!CBKeyboardState::isShiftDown())); - } else { - if (_focusedWidget) return _focusedWidget->handleKeypress(event, printable); - else return false; - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::handleMouseWheel(int Delta) { - if (_focusedWidget) return _focusedWidget->handleMouseWheel(Delta); - else return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::handleMouse(TMouseEvent event, TMouseButton button) { - bool res = CUIObject::handleMouse(event, button); - - // handle window dragging - if (!CBPlatform::isRectEmpty(&_dragRect)) { - // start drag - if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { - Rect32 dragRect = _dragRect; - int offsetX, offsetY; - getTotalOffset(&offsetX, &offsetY); - CBPlatform::offsetRect(&dragRect, _posX + offsetX, _posY + offsetY); - - if (CBPlatform::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 CUIWindow::persist(CBPersistMgr *persistMgr) { - - CUIObject::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 CUIWindow::moveFocus(bool forward) { - int i; - bool found = false; - for (i = 0; i < _widgets.getSize(); i++) { - if (_widgets[i] == _focusedWidget) { - found = true; - break; - } - } - if (!found) _focusedWidget = NULL; - - if (!_focusedWidget) { - if (_widgets.getSize() > 0) i = 0; - else return STATUS_OK; - } - - int numTries = 0; - bool done = false; - - while (numTries <= _widgets.getSize()) { - if (_widgets[i] != _focusedWidget && _widgets[i]->_canFocus && _widgets[i]->_visible && !_widgets[i]->_disable) { - _focusedWidget = _widgets[i]; - done = true; - break; - } - - if (forward) { - i++; - if (i >= _widgets.getSize()) i = 0; - } else { - i--; - if (i < 0) i = _widgets.getSize() - 1; - } - numTries++; - } - - return done ? STATUS_OK : STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::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 CUIWindow::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 CUIWindow::close() { - if (_mode == WINDOW_SYSTEM_EXCLUSIVE) { - _gameRef->unfreeze(); - } - - _mode = WINDOW_NORMAL; - _visible = false; - _ready = true; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::listen(CBScriptHolder *param1, uint32 param2) { - CUIObject *obj = (CUIObject *)param1; - - switch (obj->_type) { - case UI_BUTTON: - if (scumm_stricmp(obj->_name, "close") == 0) close(); - else return CBObject::listen(param1, param2); - break; - default: - return CBObject::listen(param1, param2); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void CUIWindow::makeFreezable(bool freezable) { - for (int i = 0; i < _widgets.getSize(); i++) - _widgets[i]->makeFreezable(freezable); - - CBObject::makeFreezable(freezable); -} - - -////////////////////////////////////////////////////////////////////////// -bool CUIWindow::getWindowObjects(CBArray &objects, bool interactiveOnly) { - for (int i = 0; i < _widgets.getSize(); i++) { - CUIObject *control = _widgets[i]; - if (control->_disable && interactiveOnly) continue; - - switch (control->_type) { - case UI_WINDOW: - ((CUIWindow *)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/UIWindow.h b/engines/wintermute/ui/UIWindow.h deleted file mode 100644 index f1d46711ff..0000000000 --- a/engines/wintermute/ui/UIWindow.h +++ /dev/null @@ -1,93 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 "UIObject.h" -#include "common/events.h" - -namespace WinterMute { - -class CUIButton; -class CBViewport; -class CUIWindow : public CUIObject { -public: - bool getWindowObjects(CBArray &Objects, bool InteractiveOnly); - - bool _pauseMusic; - void cleanup(); - virtual void makeFreezable(bool freezable); - CBViewport *_viewport; - bool _clipContents; - bool _inGame; - bool _isMenu; - bool _fadeBackground; - uint32 _fadeColor; - virtual bool handleMouseWheel(int delta); - CUIWindow *_shieldWindow; - CUIButton *_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(CUIWindow, CUIObject) - 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); - CUIWindow(CBGame *inGame); - virtual ~CUIWindow(); - virtual bool handleKeypress(Common::Event *event, bool printable = false); - CBArray _widgets; - TTextAlign _titleAlign; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - CUITiledImage *_backInactive; - CBFont *_fontInactive; - CBSprite *_imageInactive; - virtual bool listen(CBScriptHolder *param1, uint32 param2); - virtual bool saveAsText(CBDynBuffer *buffer, int indent); - - // scripting interface - virtual CScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, CScValue *value); - virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); - virtual const char *scToString(); -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/ui/ui_button.cpp b/engines/wintermute/ui/ui_button.cpp new file mode 100644 index 0000000000..5b1867b652 --- /dev/null +++ b/engines/wintermute/ui/ui_button.cpp @@ -0,0 +1,1046 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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/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(CUIButton, false) + +////////////////////////////////////////////////////////////////////////// +CUIButton::CUIButton(CBGame *inGame): CUIObject(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; +} + + +////////////////////////////////////////////////////////////////////////// +CUIButton::~CUIButton() { + 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 CUIButton::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CUIButton::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CUIButton::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; + CBParser parser(_gameRef); + + 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 CUITiledImage(_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 CUITiledImage(_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 CUITiledImage(_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 CUITiledImage(_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 CUITiledImage(_gameRef); + if (!_backFocus || DID_FAIL(_backFocus->loadFile((char *)params))) { + delete _backFocus; + _backFocus = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CBSprite(_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 CUIButton::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "BUTTON\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->_filename) + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); + if (_backHover && _backHover->_filename) + buffer->putTextIndent(indent + 2, "BACK_HOVER=\"%s\"\n", _backHover->_filename); + if (_backPress && _backPress->_filename) + buffer->putTextIndent(indent + 2, "BACK_PRESS=\"%s\"\n", _backPress->_filename); + if (_backDisable && _backDisable->_filename) + buffer->putTextIndent(indent + 2, "BACK_DISABLE=\"%s\"\n", _backDisable->_filename); + if (_backFocus && _backFocus->_filename) + buffer->putTextIndent(indent + 2, "BACK_FOCUS=\"%s\"\n", _backFocus->_filename); + + if (_image && _image->_filename) + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); + if (_imageHover && _imageHover->_filename) + buffer->putTextIndent(indent + 2, "IMAGE_HOVER=\"%s\"\n", _imageHover->_filename); + if (_imagePress && _imagePress->_filename) + buffer->putTextIndent(indent + 2, "IMAGE_PRESS=\"%s\"\n", _imagePress->_filename); + if (_imageDisable && _imageDisable->_filename) + buffer->putTextIndent(indent + 2, "IMAGE_DISABLE=\"%s\"\n", _imageDisable->_filename); + if (_imageFocus && _imageFocus->_filename) + buffer->putTextIndent(indent + 2, "IMAGE_FOCUS=\"%s\"\n", _imageFocus->_filename); + + if (_font && _font->_filename) + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); + if (_fontHover && _fontHover->_filename) + buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->_filename); + if (_fontPress && _fontPress->_filename) + buffer->putTextIndent(indent + 2, "FONT_PRESS=\"%s\"\n", _fontPress->_filename); + if (_fontDisable && _fontDisable->_filename) + buffer->putTextIndent(indent + 2, "FONT_DISABLE=\"%s\"\n", _fontDisable->_filename); + if (_fontFocus && _fontFocus->_filename) + buffer->putTextIndent(indent + 2, "FONT_FOCUS=\"%s\"\n", _fontFocus->_filename); + + if (_cursor && _cursor->_filename) + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); + + + 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("CUIButton::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 (int i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CUIButton::correctSize() { + Rect32 rect; + + CBSprite *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 CUIButton::display(int offsetX, int offsetY) { + if (!_visible) + return STATUS_OK; + + CUITiledImage *back = NULL; + CBSprite *image = NULL; + CBFont *font = 0; + + //RECT rect; + //CBPlatform::setRect(&rect, OffsetX + _posX, OffsetY + _posY, OffsetX+_posX+_width, OffsetY+_posY+_height); + //_hover = (!_disable && CBPlatform::ptInRect(&rect, _gameRef->_mousePos)!=FALSE); + _hover = (!_disable && _gameRef->_activeObject == this && (_gameRef->_interactive || _gameRef->_state == GAME_SEMI_FROZEN)); + + if ((_press && _hover && !_gameRef->_mouseLeftDown) || + (_oneTimePress && CBPlatform::getTime() - _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->_rectList.add(new CBActiveRect(_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 CUIButton::press() { + applyEvent("Press"); + if (_listenerObject) _listenerObject->listen(_listenerParamObject, _listenerParamDWORD); + if (_parentNotify && _parent) _parent->applyEvent(_name); + + _oneTimePress = false; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CUIButton::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetDisabledFont + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetDisabledFont") == 0) { + stack->correctParams(1); + CScValue *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); + CScValue *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); + CScValue *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); + CScValue *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 CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_imageDisable->_filename); + + 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 CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_imageHover->_filename); + + 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 CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_imagePress->_filename); + + 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 CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_imageFocus->_filename); + + 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 = CBPlatform::getTime(); + } + stack->pushNULL(); + + return STATUS_OK; + } + + + else return CUIObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CUIButton::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 CUIObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIButton::scSetProperty(const char *name, CScValue *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 CUIObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CUIButton::scToString() { + return "[button]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIButton::persist(CBPersistMgr *persistMgr) { + + CUIObject::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->_saving) { + _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 new file mode 100644 index 0000000000..c6538f4423 --- /dev/null +++ b/engines/wintermute/ui/ui_button.h @@ -0,0 +1,79 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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 CUIButton : public CUIObject { +public: + bool _pixelPerfect; + bool _stayPressed; + bool _centerImage; + bool _oneTimePress; + uint32 _oneTimePressTime; + DECLARE_PERSISTENT(CUIButton, CUIObject) + void press(); + virtual bool display(int offsetX = 0, int offsetY = 0); + bool _press; + bool _hover; + void correctSize(); + TTextAlign _align; + CBSprite *_imageHover; + CBSprite *_imagePress; + CBSprite *_imageDisable; + CBSprite *_imageFocus; + CBFont *_fontDisable; + CBFont *_fontPress; + CBFont *_fontHover; + CBFont *_fontFocus; + CUITiledImage *_backPress; + CUITiledImage *_backHover; + CUITiledImage *_backDisable; + CUITiledImage *_backFocus; + CUIButton(CBGame *inGame = NULL); + virtual ~CUIButton(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..237b944332 --- /dev/null +++ b/engines/wintermute/ui/ui_edit.cpp @@ -0,0 +1,857 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/platform_osystem.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(CUIEdit, false) + +////////////////////////////////////////////////////////////////////////// +CUIEdit::CUIEdit(CBGame *inGame): CUIObject(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; +} + + +////////////////////////////////////////////////////////////////////////// +CUIEdit::~CUIEdit() { + if (!_sharedFonts) { + if (_fontSelected) _gameRef->_fontStorage->removeFont(_fontSelected); + } + + delete[] _cursorChar; + _cursorChar = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIEdit::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CUIEdit::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CUIEdit::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; + CBParser parser(_gameRef); + + 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 CUITiledImage(_gameRef); + if (!_back || DID_FAIL(_back->loadFile((char *)params))) { + delete _back; + _back = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new CBSprite(_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 CBSprite(_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 CUIEdit::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "EDIT\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->_filename) + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); + + if (_image && _image->_filename) + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); + + if (_font && _font->_filename) + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); + if (_fontSelected && _fontSelected->_filename) + buffer->putTextIndent(indent + 2, "FONT_SELECTED=\"%s\"\n", _fontSelected->_filename); + + if (_cursor && _cursor->_filename) + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); + + 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 (int i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CUIEdit::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CUIObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CUIEdit::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 CUIObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIEdit::scSetProperty(const char *name, CScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // SelStart + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SelStart") == 0) { + _selStart = value->getInt(); + _selStart = MAX(_selStart, 0); + _selStart = MIN((size_t)_selStart, strlen(_text)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SelEnd + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SelEnd") == 0) { + _selEnd = value->getInt(); + _selEnd = MAX(_selEnd, 0); + _selEnd = MIN((size_t)_selEnd, strlen(_text)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorBlinkRate + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorBlinkRate") == 0) { + _cursorBlinkRate = 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 CUIObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CUIEdit::scToString() { + return "[edit]"; +} + + +////////////////////////////////////////////////////////////////////////// +void CUIEdit::setCursorChar(const char *character) { + if (!character) return; + delete[] _cursorChar; + _cursorChar = new char [strlen(character) + 1]; + if (_cursorChar) strcpy(_cursorChar, character); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIEdit::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 + CBFont *font; + CBFont *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 = MIN((size_t)_selStart, strlen(_text)); + _selEnd = 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 (CBPlatform::getTime() - _lastBlinkTime >= _cursorBlinkRate) { + _lastBlinkTime = CBPlatform::getTime(); + _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 (CBPlatform::getTime() - _lastBlinkTime >= _cursorBlinkRate) { + _lastBlinkTime = CBPlatform::getTime(); + _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->_rectList.add(new CBActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); + + + _gameRef->_textEncoding = OrigEncoding; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIEdit::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 (CBKeyboardState::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 (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; + handled = true; + break; + + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_DOWN: + _selEnd++; + if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; + handled = true; + break; + + case Common::KEYCODE_HOME: + if (_gameRef->_textRTL) { + _selEnd = strlen(_text); + if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; + } else { + _selEnd = 0; + if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; + } + handled = true; + break; + + case Common::KEYCODE_END: + if (_gameRef->_textRTL) { + _selEnd = 0; + if (!CBKeyboardState::isShiftDown()) _selStart = _selEnd; + } else { + _selEnd = strlen(_text); + if (!CBKeyboardState::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, (byte *)StringUtil::wideToAnsi(wstr).c_str(), 1); + + if (_gameRef->_textRTL) _selEnd = _selStart; + else _selStart = _selEnd; + + return true; + } + + return false; +} + + + +////////////////////////////////////////////////////////////////////////// +int CUIEdit::deleteChars(int start, int end) { + if (start > end) CBUtils::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(_name); + + return end - start; +} + + +////////////////////////////////////////////////////////////////////////// +int CUIEdit::insertChars(int pos, 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(_name); + + return num; +} + + + +////////////////////////////////////////////////////////////////////////// +bool CUIEdit::persist(CBPersistMgr *persistMgr) { + + CUIObject::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->_saving) { + _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 new file mode 100644 index 0000000000..400cd7b578 --- /dev/null +++ b/engines/wintermute/ui/ui_edit.h @@ -0,0 +1,72 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_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 CBFont; +class CUIEdit : public CUIObject { +public: + DECLARE_PERSISTENT(CUIEdit, CUIObject) + int _maxLength; + int insertChars(int pos, 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; + CBFont *_fontSelected; + CUIEdit(CBGame *inGame); + virtual ~CUIEdit(); + + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..012ff0390f --- /dev/null +++ b/engines/wintermute/ui/ui_entity.cpp @@ -0,0 +1,339 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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(CUIEntity, false) + +////////////////////////////////////////////////////////////////////////// +CUIEntity::CUIEntity(CBGame *inGame): CUIObject(inGame) { + _type = UI_CUSTOM; + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CUIEntity::~CUIEntity() { + if (_entity) _gameRef->unregisterObject(_entity); + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIEntity::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CUIEntity::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CUIEntity::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; + CBParser parser(_gameRef); + + 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 CUIEntity::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "ENTITY_CONTAINER\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + + 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->_filename) + buffer->putTextIndent(indent + 2, "ENTITY=\"%s\"\n", _entity->_filename); + + buffer->putTextIndent(indent + 2, "\n"); + + // scripts + for (int i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CUIEntity::setEntity(const char *filename) { + if (_entity) _gameRef->unregisterObject(_entity); + _entity = new CAdEntity(_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 CUIEntity::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 CUIEntity::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CUIObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CUIEntity::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 CUIObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIEntity::scSetProperty(const char *name, CScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Freezable + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Freezable") == 0) { + if (_entity) _entity->makeFreezable(value->getBool()); + return STATUS_OK; + } else return CUIObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CUIEntity::scToString() { + return "[entity container]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIEntity::persist(CBPersistMgr *persistMgr) { + + CUIObject::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 new file mode 100644 index 0000000000..6873000681 --- /dev/null +++ b/engines/wintermute/ui/ui_entity.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_UIENTITY_H +#define WINTERMUTE_UIENTITY_H + +#include "engines/wintermute/ui/ui_object.h" + +namespace WinterMute { +class CAdEntity; +class CUIEntity : public CUIObject { +public: + DECLARE_PERSISTENT(CUIEntity, CUIObject) + CUIEntity(CBGame *inGame); + virtual ~CUIEntity(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + virtual bool display(int offsetX = 0, int offsetY = 0); + CAdEntity *_entity; + bool setEntity(const char *filename); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..605b5b74b1 --- /dev/null +++ b/engines/wintermute/ui/ui_object.cpp @@ -0,0 +1,589 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/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(CUIObject, false) + +////////////////////////////////////////////////////////////////////////// +CUIObject::CUIObject(CBGame *inGame): CBObject(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; +} + + +////////////////////////////////////////////////////////////////////////// +CUIObject::~CUIObject() { + if (!_gameRef->_loadInProgress) CSysClassRegistry::getInstance()->enumInstances(CBGame::invalidateValues, "CScValue", (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 CUIObject::setText(const char *text) { + if (_text) delete [] _text; + _text = new char [strlen(text) + 1]; + if (_text) { + strcpy(_text, text); + for (int i = 0; i < strlen(_text); i++) { + if (_text[i] == '|') _text[i] = '\n'; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIObject::display(int offsetX, int offsetY) { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CUIObject::setListener(CBScriptHolder *object, CBScriptHolder *listenerObject, uint32 listenerParam) { + _listenerObject = object; + _listenerParamObject = listenerObject; + _listenerParamDWORD = listenerParam; +} + + +////////////////////////////////////////////////////////////////////////// +void CUIObject::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 CUIObject::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetFont + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetFont") == 0) { + stack->correctParams(1); + CScValue *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); + CScValue *val = stack->pop(); + + /* const char *filename = */ val->getString(); + + delete _image; + _image = NULL; + if (val->isNULL()) { + stack->pushBool(true); + return STATUS_OK; + } + + _image = new CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_image->_filename); + + 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) { + CUIWindow *win = (CUIWindow *)_parent; + + int i; + bool found = false; + CScValue *val = stack->pop(); + // find directly + if (val->isNative()) { + CUIObject *widget = (CUIObject *)val->getNative(); + for (i = 0; i < win->_widgets.getSize(); i++) { + if (win->_widgets[i] == widget) { + found = true; + break; + } + } + } + // find by name + else { + const char *findName = val->getString(); + for (i = 0; i < win->_widgets.getSize(); i++) { + if (scumm_stricmp(win->_widgets[i]->_name, findName) == 0) { + found = true; + break; + } + } + } + + if (found) { + bool done = false; + for (int j = 0; j < win->_widgets.getSize(); j++) { + if (win->_widgets[j] == this) { + if (strcmp(name, "MoveAfter") == 0) i++; + if (j >= i) j++; + + win->_widgets.insertAt(i, this); + win->_widgets.removeAt(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) { + CUIWindow *win = (CUIWindow *)_parent; + for (int i = 0; i < win->_widgets.getSize(); i++) { + if (win->_widgets[i] == this) { + win->_widgets.removeAt(i); + win->_widgets.insertAt(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) { + CUIWindow *win = (CUIWindow *)_parent; + for (int i = 0; i < win->_widgets.getSize(); i++) { + if (win->_widgets[i] == this) { + win->_widgets.removeAt(i); + win->_widgets.add(this); + break; + } + } + stack->pushBool(true); + } else stack->pushBool(false); + + return STATUS_OK; + } + + else return CBObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CUIObject::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(_name); + 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) { + CUIWindow *win = (CUIWindow *)_parent; + for (int i = 0; i < win->_widgets.getSize(); i++) { + if (win->_widgets[i] == this) { + if (strcmp(name, "NextSibling") == 0) { + if (i < win->_widgets.getSize() - 1) _scValue->setNative(win->_widgets[i + 1], true); + } else { + if (i > 0) _scValue->setNative(win->_widgets[i - 1], true); + } + break; + } + } + } + return _scValue; + } + + else return CBObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIObject::scSetProperty(const char *name, CScValue *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 CBObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CUIObject::scToString() { + return "[ui_object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIObject::isFocused() { + if (!_gameRef->_focusedWindow) return false; + if (_gameRef->_focusedWindow == this) return true; + + CUIObject *obj = _gameRef->_focusedWindow; + while (obj) { + if (obj == this) return true; + else obj = obj->_focusedWidget; + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIObject::handleMouse(TMouseEvent event, TMouseButton button) { + // handle focus change + if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { + focus(); + } + return CBObject::handleMouse(event, button); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIObject::focus() { + CUIObject *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((CUIWindow *)obj); + } + + obj = obj->_parent; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIObject::getTotalOffset(int *offsetX, int *offsetY) { + int offX = 0, offY = 0; + + CUIObject *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 CUIObject::persist(CBPersistMgr *persistMgr) { + + CBObject::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 CUIObject::saveAsText(CBDynBuffer *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 new file mode 100644 index 0000000000..35bd092592 --- /dev/null +++ b/engines/wintermute/ui/ui_object.h @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_UIOBJECT_H +#define WINTERMUTE_UIOBJECT_H + + +#include "engines/wintermute/base/base_object.h" +#include "engines/wintermute/dctypes.h" // Added by ClassView + +namespace WinterMute { + +class CUITiledImage; +class CBFont; +class CUIObject : public CBObject { +public: + + bool getTotalOffset(int *offsetX, int *offsetY); + bool _canFocus; + bool focus(); + virtual bool handleMouse(TMouseEvent event, TMouseButton button); + bool isFocused(); + bool _parentNotify; + DECLARE_PERSISTENT(CUIObject, CBObject) + CUIObject *_parent; + virtual bool display(int offsetX = 0, int offsetY = 0); + virtual void correctSize(); + bool _sharedFonts; + bool _sharedImages; + void setText(const char *text); + char *_text; + CBFont *_font; + bool _visible; + CUITiledImage *_back; + bool _disable; + CUIObject(CBGame *inGame = NULL); + virtual ~CUIObject(); + int _width; + int _height; + TUIObjectType _type; + CBSprite *_image; + void setListener(CBScriptHolder *object, CBScriptHolder *listenerObject, uint32 listenerParam); + CBScriptHolder *_listenerParamObject; + uint32 _listenerParamDWORD; + CBScriptHolder *_listenerObject; + CUIObject *_focusedWidget; + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..6309d05a1e --- /dev/null +++ b/engines/wintermute/ui/ui_text.cpp @@ -0,0 +1,489 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CUIText, false) + +////////////////////////////////////////////////////////////////////////// +CUIText::CUIText(CBGame *inGame): CUIObject(inGame) { + _textAlign = TAL_LEFT; + _verticalAlign = VAL_CENTER; + _type = UI_STATIC; + _canFocus = false; +} + + +////////////////////////////////////////////////////////////////////////// +CUIText::~CUIText() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIText::display(int offsetX, int offsetY) { + if (!_visible) return STATUS_OK; + + + CBFont *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 CBActiveRect(_gameRef, this, NULL, OffsetX + _posX, OffsetY + _posY, _width, _height, 100, 100, false)); + + return STATUS_OK; +} + + + +////////////////////////////////////////////////////////////////////////// +bool CUIText::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CUIText::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CUIText::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; + CBParser parser(_gameRef); + + 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 CUITiledImage(_gameRef); + if (!_back || DID_FAIL(_back->loadFile((char *)params))) { + delete _back; + _back = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new CBSprite(_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 CBSprite(_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 CUIText::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "STATIC\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->_filename) + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); + + if (_image && _image->_filename) + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); + + if (_font && _font->_filename) + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); + + if (_cursor && _cursor->_filename) + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); + + 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("CUIText::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 (int i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CUIText::scCallMethod(CScScript *script, CScStack *stack, CScStack *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 CUIObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CUIText::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 CUIObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIText::scSetProperty(const char *name, CScValue *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 CUIObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CUIText::scToString() { + return "[static]"; +} + + + +////////////////////////////////////////////////////////////////////////// +bool CUIText::persist(CBPersistMgr *persistMgr) { + + CUIObject::persist(persistMgr); + persistMgr->transfer(TMEMBER_INT(_textAlign)); + persistMgr->transfer(TMEMBER_INT(_verticalAlign)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIText::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 new file mode 100644 index 0000000000..dc633dc042 --- /dev/null +++ b/engines/wintermute/ui/ui_text.h @@ -0,0 +1,60 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_UITEXT_H +#define WINTERMUTE_UITEXT_H + + +#include "engines/wintermute/ui/ui_object.h" + +namespace WinterMute { + +class CUIText : public CUIObject { +private: + bool sizeToFit(); +public: + virtual bool display(int offsetX, int offsetY); + DECLARE_PERSISTENT(CUIText, CUIObject) + CUIText(CBGame *inGame = NULL); + virtual ~CUIText(); + TTextAlign _textAlign; + TVerticalAlign _verticalAlign; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *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 new file mode 100644 index 0000000000..39b39b556d --- /dev/null +++ b/engines/wintermute/ui/ui_tiled_image.cpp @@ -0,0 +1,370 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/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(CUITiledImage, false) + +////////////////////////////////////////////////////////////////////////// +CUITiledImage::CUITiledImage(CBGame *inGame): CBObject(inGame) { + _image = NULL; + + CBPlatform::setRectEmpty(&_upLeft); + CBPlatform::setRectEmpty(&_upMiddle); + CBPlatform::setRectEmpty(&_upRight); + CBPlatform::setRectEmpty(&_middleLeft); + CBPlatform::setRectEmpty(&_middleMiddle); + CBPlatform::setRectEmpty(&_middleRight); + CBPlatform::setRectEmpty(&_downLeft); + CBPlatform::setRectEmpty(&_downMiddle); + CBPlatform::setRectEmpty(&_downRight); +} + + +////////////////////////////////////////////////////////////////////////// +CUITiledImage::~CUITiledImage() { + delete _image; + _image = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUITiledImage::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 CUITiledImage::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CUITiledImage::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CUITiledImage::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; + CBParser parser(_gameRef); + 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 CBSubFrame(_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 + CBPlatform::setRect(&_upLeft, 0, 0, h1, v1); + CBPlatform::setRect(&_upMiddle, h1, 0, h1 + h2, v1); + CBPlatform::setRect(&_upRight, h1 + h2, 0, h1 + h2 + h3, v1); + + // middle row + CBPlatform::setRect(&_middleLeft, 0, v1, h1, v1 + v2); + CBPlatform::setRect(&_middleMiddle, h1, v1, h1 + h2, v1 + v2); + CBPlatform::setRect(&_middleRight, h1 + h2, v1, h1 + h2 + h3, v1 + v2); + + // down row + CBPlatform::setRect(&_downLeft, 0, v1 + v2, h1, v1 + v2 + v3); + CBPlatform::setRect(&_downMiddle, h1, v1 + v2, h1 + h2, v1 + v2 + v3); + CBPlatform::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 (CBPlatform::isRectEmpty(&_upLeft)) CBPlatform::setRect(&_upLeft, 0, 0, width, height); + if (CBPlatform::isRectEmpty(&_upMiddle)) CBPlatform::setRect(&_upMiddle, width, 0, 2 * width, height); + if (CBPlatform::isRectEmpty(&_upRight)) CBPlatform::setRect(&_upRight, 2 * width, 0, 3 * width, height); + + if (CBPlatform::isRectEmpty(&_middleLeft)) CBPlatform::setRect(&_middleLeft, 0, height, width, 2 * height); + if (CBPlatform::isRectEmpty(&_middleMiddle)) CBPlatform::setRect(&_middleMiddle, width, height, 2 * width, 2 * height); + if (CBPlatform::isRectEmpty(&_middleRight)) CBPlatform::setRect(&_middleRight, 2 * width, height, 3 * width, 2 * height); + + if (CBPlatform::isRectEmpty(&_downLeft)) CBPlatform::setRect(&_downLeft, 0, 2 * height, width, 3 * height); + if (CBPlatform::isRectEmpty(&_downMiddle)) CBPlatform::setRect(&_downMiddle, width, 2 * height, 2 * width, 3 * height); + if (CBPlatform::isRectEmpty(&_downRight)) CBPlatform::setRect(&_downRight, 2 * width, 2 * height, 3 * width, 3 * height); + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CUITiledImage::saveAsText(CBDynBuffer *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 + CBBase::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CUITiledImage::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 CUITiledImage::persist(CBPersistMgr *persistMgr) { + CBObject::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 new file mode 100644 index 0000000000..79adf7caac --- /dev/null +++ b/engines/wintermute/ui/ui_tiled_image.h @@ -0,0 +1,63 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_UITILEDIMAGE_H +#define WINTERMUTE_UITILEDIMAGE_H + + +#include "engines/wintermute/ui/ui_object.h" +#include "common/rect.h" + +namespace WinterMute { +class CBSubFrame; +class CUITiledImage : public CBObject { +public: + DECLARE_PERSISTENT(CUITiledImage, CBObject) + void correctSize(int *width, int *height); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + bool display(int x, int y, int width, int height); + CUITiledImage(CBGame *inGame = NULL); + virtual ~CUITiledImage(); + CBSubFrame *_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 new file mode 100644 index 0000000000..269744a3c2 --- /dev/null +++ b/engines/wintermute/ui/ui_window.cpp @@ -0,0 +1,1327 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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_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(CUIWindow, false) + +////////////////////////////////////////////////////////////////////////// +CUIWindow::CUIWindow(CBGame *inGame): CUIObject(inGame) { + CBPlatform::setRectEmpty(&_titleRect); + CBPlatform::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; +} + + +////////////////////////////////////////////////////////////////////////// +CUIWindow::~CUIWindow() { + close(); + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CUIWindow::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 (int i = 0; i < _widgets.getSize(); i++) delete _widgets[i]; + _widgets.removeAll(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::display(int offsetX, int offsetY) { + // go exclusive + if (_mode == WINDOW_EXCLUSIVE || _mode == WINDOW_SYSTEM_EXCLUSIVE) { + if (!_shieldWindow) _shieldWindow = new CUIWindow(_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 CUIButton(_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) _gameRef->_renderer->fadeToColor(_fadeColor); + + 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 CBViewport(_gameRef); + if (_viewport) { + _viewport->setRect(_posX + offsetX, _posY + offsetY, _posX + _width + offsetX, _posY + _height + offsetY); + _gameRef->pushViewport(_viewport); + popViewport = true; + } + } + + + CUITiledImage *back = _back; + CBSprite *image = _image; + CBFont *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 (!CBPlatform::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->_rectList.add(new CBActiveRect(_gameRef, this, NULL, _posX + offsetX, _posY + offsetY, _width, _height, 100, 100, false)); + + for (int i = 0; i < _widgets.getSize(); i++) { + _widgets[i]->display(_posX + offsetX, _posY + offsetY); + } + + if (_alphaColor != 0) + _gameRef->_renderer->_forceAlphaColor = 0; + + if (popViewport) + _gameRef->popViewport(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::loadFile(const char *filename) { + byte *buffer = _gameRef->_fileManager->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "CUIWindow::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + _filename = new char [strlen(filename) + 1]; + strcpy(_filename, 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 CUIWindow::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; + CBParser parser(_gameRef); + + 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 CUITiledImage(_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 CUITiledImage(_gameRef); + if (!_backInactive || DID_FAIL(_backInactive->loadFile((char *)params))) { + delete _backInactive; + _backInactive = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new CBSprite(_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 CBSprite(_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 CBSprite(_gameRef); + if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { + delete _cursor; + _cursor = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_BUTTON: { + CUIButton *btn = new CUIButton(_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: { + CUIText *text = new CUIText(_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: { + CUIEdit *edit = new CUIEdit(_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: { + CUIWindow *win = new CUIWindow(_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 CUIWindow::saveAsText(CBDynBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "WINDOW\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->_filename) + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename); + if (_backInactive && _backInactive->_filename) + buffer->putTextIndent(indent + 2, "BACK_INACTIVE=\"%s\"\n", _backInactive->_filename); + + if (_image && _image->_filename) + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename); + if (_imageInactive && _imageInactive->_filename) + buffer->putTextIndent(indent + 2, "IMAGE_INACTIVE=\"%s\"\n", _imageInactive->_filename); + + if (_font && _font->_filename) + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename); + if (_fontInactive && _fontInactive->_filename) + buffer->putTextIndent(indent + 2, "FONT_INACTIVE=\"%s\"\n", _fontInactive->_filename); + + if (_cursor && _cursor->_filename) + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename); + + 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 (!CBPlatform::isRectEmpty(&_titleRect)) { + buffer->putTextIndent(indent + 2, "TITLE_RECT { %d, %d, %d, %d }\n", _titleRect.left, _titleRect.top, _titleRect.right, _titleRect.bottom); + } + + if (!CBPlatform::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 (int i = 0; i < _scripts.getSize(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + CBBase::saveAsText(buffer, indent + 2); + + // controls + for (int i = 0; i < _widgets.getSize(); i++) + _widgets[i]->saveAsText(buffer, indent + 2); + + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::enableWidget(const char *name, bool Enable) { + for (int i = 0; i < _widgets.getSize(); i++) { + if (scumm_stricmp(_widgets[i]->_name, name) == 0) _widgets[i]->_disable = !Enable; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::showWidget(const char *name, bool Visible) { + for (int i = 0; i < _widgets.getSize(); i++) { + if (scumm_stricmp(_widgets[i]->_name, name) == 0) _widgets[i]->_visible = Visible; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GetWidget / GetControl + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetWidget") == 0 || strcmp(name, "GetControl") == 0) { + stack->correctParams(1); + CScValue *val = stack->pop(); + if (val->getType() == VAL_INT) { + int widget = val->getInt(); + if (widget < 0 || widget >= _widgets.getSize()) stack->pushNULL(); + else stack->pushNative(_widgets[widget], true); + } else { + for (int i = 0; i < _widgets.getSize(); i++) { + if (scumm_stricmp(_widgets[i]->_name, 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 CBSprite(_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->_filename) stack->pushNULL(); + else stack->pushString(_imageInactive->_filename); + + 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); + + CScValue *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); + CScValue *val = stack->pop(); + + CUIButton *btn = new CUIButton(_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); + CScValue *val = stack->pop(); + + CUIText *sta = new CUIText(_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); + CScValue *val = stack->pop(); + + CUIEdit *edi = new CUIEdit(_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); + CScValue *val = stack->pop(); + + CUIWindow *win = new CUIWindow(_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); + CScValue *val = stack->pop(); + CUIObject *obj = (CUIObject *)val->getNative(); + + for (int i = 0; i < _widgets.getSize(); i++) { + if (_widgets[i] == obj) { + delete _widgets[i]; + _widgets.removeAt(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 CUIObject::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CUIWindow::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.getSize()); + 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 CUIObject::scGetProperty(name); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::scSetProperty(const char *name, CScValue *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 CUIObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CUIWindow::scToString() { + return "[window]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::handleKeypress(Common::Event *event, bool printable) { +//TODO + if (event->type == Common::EVENT_KEYDOWN && event->kbd.keycode == Common::KEYCODE_TAB) { + return DID_SUCCEED(moveFocus(!CBKeyboardState::isShiftDown())); + } else { + if (_focusedWidget) return _focusedWidget->handleKeypress(event, printable); + else return false; + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::handleMouseWheel(int Delta) { + if (_focusedWidget) return _focusedWidget->handleMouseWheel(Delta); + else return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::handleMouse(TMouseEvent event, TMouseButton button) { + bool res = CUIObject::handleMouse(event, button); + + // handle window dragging + if (!CBPlatform::isRectEmpty(&_dragRect)) { + // start drag + if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { + Rect32 dragRect = _dragRect; + int offsetX, offsetY; + getTotalOffset(&offsetX, &offsetY); + CBPlatform::offsetRect(&dragRect, _posX + offsetX, _posY + offsetY); + + if (CBPlatform::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 CUIWindow::persist(CBPersistMgr *persistMgr) { + + CUIObject::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 CUIWindow::moveFocus(bool forward) { + int i; + bool found = false; + for (i = 0; i < _widgets.getSize(); i++) { + if (_widgets[i] == _focusedWidget) { + found = true; + break; + } + } + if (!found) _focusedWidget = NULL; + + if (!_focusedWidget) { + if (_widgets.getSize() > 0) i = 0; + else return STATUS_OK; + } + + int numTries = 0; + bool done = false; + + while (numTries <= _widgets.getSize()) { + if (_widgets[i] != _focusedWidget && _widgets[i]->_canFocus && _widgets[i]->_visible && !_widgets[i]->_disable) { + _focusedWidget = _widgets[i]; + done = true; + break; + } + + if (forward) { + i++; + if (i >= _widgets.getSize()) i = 0; + } else { + i--; + if (i < 0) i = _widgets.getSize() - 1; + } + numTries++; + } + + return done ? STATUS_OK : STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::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 CUIWindow::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 CUIWindow::close() { + if (_mode == WINDOW_SYSTEM_EXCLUSIVE) { + _gameRef->unfreeze(); + } + + _mode = WINDOW_NORMAL; + _visible = false; + _ready = true; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::listen(CBScriptHolder *param1, uint32 param2) { + CUIObject *obj = (CUIObject *)param1; + + switch (obj->_type) { + case UI_BUTTON: + if (scumm_stricmp(obj->_name, "close") == 0) close(); + else return CBObject::listen(param1, param2); + break; + default: + return CBObject::listen(param1, param2); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CUIWindow::makeFreezable(bool freezable) { + for (int i = 0; i < _widgets.getSize(); i++) + _widgets[i]->makeFreezable(freezable); + + CBObject::makeFreezable(freezable); +} + + +////////////////////////////////////////////////////////////////////////// +bool CUIWindow::getWindowObjects(CBArray &objects, bool interactiveOnly) { + for (int i = 0; i < _widgets.getSize(); i++) { + CUIObject *control = _widgets[i]; + if (control->_disable && interactiveOnly) continue; + + switch (control->_type) { + case UI_WINDOW: + ((CUIWindow *)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 new file mode 100644 index 0000000000..6fe24c6a2c --- /dev/null +++ b/engines/wintermute/ui/ui_window.h @@ -0,0 +1,93 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_UIWINDOW_H +#define WINTERMUTE_UIWINDOW_H + + +#include "engines/wintermute/ui/ui_object.h" +#include "common/events.h" + +namespace WinterMute { + +class CUIButton; +class CBViewport; +class CUIWindow : public CUIObject { +public: + bool getWindowObjects(CBArray &Objects, bool InteractiveOnly); + + bool _pauseMusic; + void cleanup(); + virtual void makeFreezable(bool freezable); + CBViewport *_viewport; + bool _clipContents; + bool _inGame; + bool _isMenu; + bool _fadeBackground; + uint32 _fadeColor; + virtual bool handleMouseWheel(int delta); + CUIWindow *_shieldWindow; + CUIButton *_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(CUIWindow, CUIObject) + 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); + CUIWindow(CBGame *inGame); + virtual ~CUIWindow(); + virtual bool handleKeypress(Common::Event *event, bool printable = false); + CBArray _widgets; + TTextAlign _titleAlign; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + CUITiledImage *_backInactive; + CBFont *_fontInactive; + CBSprite *_imageInactive; + virtual bool listen(CBScriptHolder *param1, uint32 param2); + virtual bool saveAsText(CBDynBuffer *buffer, int indent); + + // scripting interface + virtual CScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, CScValue *value); + virtual bool scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name); + virtual const char *scToString(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/utils/ConvertUTF.cpp b/engines/wintermute/utils/ConvertUTF.cpp deleted file mode 100644 index 8f7d6d2124..0000000000 --- a/engines/wintermute/utils/ConvertUTF.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Source code file. - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Sept 2001: fixed const & error conditions per - mods suggested by S. Parent & A. Lillich. - June 2002: Tim Dodd added detection and handling of incomplete - source sequences, enhanced error detection, added casts - to eliminate compiler warnings. - July 2003: slight mods to back out aggressive FFFE detection. - Jan 2004: updated switches in from-UTF8 conversions. - Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. - - See the header file "ConvertUTF.h" for complete documentation. - ------------------------------------------------------------------------- */ - - -#include "ConvertUTF.h" -#ifdef CVTUTF_DEBUG -#include -#endif - -static const int halfShift = 10; /* used for shifting by 10 bits */ - -static const UTF32 halfBase = 0x0010000UL; -static const UTF32 halfMask = 0x3FFUL; - -#define UNI_SUR_HIGH_START (UTF32)0xD800 -#define UNI_SUR_HIGH_END (UTF32)0xDBFF -#define UNI_SUR_LOW_START (UTF32)0xDC00 -#define UNI_SUR_LOW_END (UTF32)0xDFFF -#define false 0 -#define true 1 - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF16( - const UTF32 **sourceStart, const UTF32 *sourceEnd, - UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32 *source = *sourceStart; - UTF16 *target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - if (target >= targetEnd) { - result = targetExhausted; - break; - } - ch = *source++; - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_LEGAL_UTF32) { - if (flags == strictConversion) { - result = sourceIllegal; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - --source; /* Back up source pointer! */ - result = targetExhausted; - break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF32( - const UTF16 **sourceStart, const UTF16 *sourceEnd, - UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16 *source = *sourceStart; - UTF32 *target = *targetStart; - UTF32 ch, ch2; - while (source < sourceEnd) { - const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - if (target >= targetEnd) { - source = oldSource; /* Back up source pointer! */ - result = targetExhausted; - break; - } - *target++ = ch; - } - *sourceStart = source; - *targetStart = target; -#ifdef CVTUTF_DEBUG - if (result == sourceIllegal) { - fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); - fflush(stderr); - } -#endif - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Index into the table below with the first byte of a UTF-8 sequence to - * get the number of trailing bytes that are supposed to follow it. - * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is - * left as-is for anyone who may want to do such conversion, which was - * allowed in earlier algorithms. - */ -static const char trailingBytesForUTF8[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 -}; - -/* - * Magic values subtracted from a buffer value during UTF8 conversion. - * This table contains as many values as there might be trailing bytes - * in a UTF-8 sequence. - */ -static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL - }; - -/* - * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed - * into the first byte, depending on how many bytes follow. There are - * as many entries in this table as there are UTF-8 sequence types. - * (I.e., one byte sequence, two byte... etc.). Remember that sequencs - * for *legal* UTF-8 will be 4 or fewer bytes total. - */ -static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -/* --------------------------------------------------------------------- */ - -/* The interface converts a whole buffer to avoid function-call overhead. - * Constants have been gathered. Loops & conditionals have been removed as - * much as possible for efficiency, in favor of drop-through switches. - * (See "Note A" at the bottom of the file for equivalent code.) - * If your compiler supports it, the "isLegalUTF8" call can be turned - * into an inline function. - */ - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF8( - const UTF16 **sourceStart, const UTF16 *sourceEnd, - UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16 *source = *sourceStart; - UTF8 *target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - UTF32 ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { - bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { - bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { - bytesToWrite = 3; - } else if (ch < (UTF32)0x110000) { - bytesToWrite = 4; - } else { - bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; - result = targetExhausted; - break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: - *--target = (UTF8)((ch | byteMark) & byteMask); - ch >>= 6; - case 3: - *--target = (UTF8)((ch | byteMark) & byteMask); - ch >>= 6; - case 2: - *--target = (UTF8)((ch | byteMark) & byteMask); - ch >>= 6; - case 1: - *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Utility routine to tell whether a sequence of bytes is legal UTF-8. - * This must be called with the length pre-determined by the first byte. - * If not calling this from ConvertUTF8to*, then the length can be set by: - * length = trailingBytesForUTF8[*source]+1; - * and the sequence is illegal right away if there aren't that many bytes - * available. - * If presented with a length > 4, this returns false. The Unicode - * definition of UTF-8 goes up to 4-byte sequences. - */ - -static Boolean isLegalUTF8(const UTF8 *source, int length) { - UTF8 a; - const UTF8 *srcptr = source + length; - switch (length) { - default: - return false; - /* Everything else falls through when "true"... */ - case 4: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 3: - if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 2: - if ((a = (*--srcptr)) > 0xBF) return false; - - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: - if (a < 0xA0) return false; - break; - case 0xED: - if (a > 0x9F) return false; - break; - case 0xF0: - if (a < 0x90) return false; - break; - case 0xF4: - if (a > 0x8F) return false; - break; - default: - if (a < 0x80) return false; - } - - case 1: - if (*source >= 0x80 && *source < 0xC2) return false; - } - if (*source > 0xF4) return false; - return true; -} - -/* --------------------------------------------------------------------- */ - -/* - * Exported function to return whether a UTF-8 sequence is legal or not. - * This is not used here; it's just exported. - */ -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { - int length = trailingBytesForUTF8[*source] + 1; - if (source + length > sourceEnd) { - return false; - } - return isLegalUTF8(source, length); -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF16( - const UTF8 **sourceStart, const UTF8 *sourceEnd, - UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8 *source = *sourceStart; - UTF16 *target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; - break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead + 1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: - ch += *source++; - ch <<= 6; /* remember, illegal UTF-8 */ - case 4: - ch += *source++; - ch <<= 6; /* remember, illegal UTF-8 */ - case 3: - ch += *source++; - ch <<= 6; - case 2: - ch += *source++; - ch <<= 6; - case 1: - ch += *source++; - ch <<= 6; - case 0: - ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead + 1); /* Back up source pointer! */ - result = targetExhausted; - break; - } - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead + 1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - source -= (extraBytesToRead + 1); /* return to the start */ - break; /* Bail out; shouldn't continue */ - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - source -= (extraBytesToRead + 1); /* Back up source pointer! */ - result = targetExhausted; - break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF8( - const UTF32 **sourceStart, const UTF32 *sourceEnd, - UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32 *source = *sourceStart; - UTF8 *target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* - * Figure out how many bytes the result will require. Turn any - * illegally large UTF32 things (> Plane 17) into replacement chars. - */ - if (ch < (UTF32)0x80) { - bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { - bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { - bytesToWrite = 3; - } else if (ch <= UNI_MAX_LEGAL_UTF32) { - bytesToWrite = 4; - } else { - bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - result = sourceIllegal; - } - - target += bytesToWrite; - if (target > targetEnd) { - --source; /* Back up source pointer! */ - target -= bytesToWrite; - result = targetExhausted; - break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: - *--target = (UTF8)((ch | byteMark) & byteMask); - ch >>= 6; - case 3: - *--target = (UTF8)((ch | byteMark) & byteMask); - ch >>= 6; - case 2: - *--target = (UTF8)((ch | byteMark) & byteMask); - ch >>= 6; - case 1: - *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF32( - const UTF8 **sourceStart, const UTF8 *sourceEnd, - UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8 *source = *sourceStart; - UTF32 *target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; - break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead + 1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: - ch += *source++; - ch <<= 6; - case 4: - ch += *source++; - ch <<= 6; - case 3: - ch += *source++; - ch <<= 6; - case 2: - ch += *source++; - ch <<= 6; - case 1: - ch += *source++; - ch <<= 6; - case 0: - ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead + 1); /* Back up the source pointer! */ - result = targetExhausted; - break; - } - if (ch <= UNI_MAX_LEGAL_UTF32) { - /* - * UTF-16 surrogate values are illegal in UTF-32, and anything - * over Plane 17 (> 0x10FFFF) is illegal. - */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead + 1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = ch; - } - } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ - result = sourceIllegal; - *target++ = UNI_REPLACEMENT_CHAR; - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- - - Note A. - The fall-through switches in UTF-8 reading code save a - temp variable, some decrements & conditionals. The switches - are equivalent to the following loop: - { - int tmpBytesToRead = extraBytesToRead+1; - do { - ch += *source++; - --tmpBytesToRead; - if (tmpBytesToRead) ch <<= 6; - } while (tmpBytesToRead > 0); - } - In UTF-8 writing code, the switches on "bytesToWrite" are - similarly unrolled loops. - - --------------------------------------------------------------------- */ diff --git a/engines/wintermute/utils/ConvertUTF.h b/engines/wintermute/utils/ConvertUTF.h deleted file mode 100644 index 03a8bb2bae..0000000000 --- a/engines/wintermute/utils/ConvertUTF.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Header file. - - Several funtions are included here, forming a complete set of - conversions between the three formats. UTF-7 is not included - here, but is handled in a separate source file. - - Each of these routines takes pointers to input buffers and output - buffers. The input buffers are const. - - Each routine converts the text between *sourceStart and sourceEnd, - putting the result into the buffer between *targetStart and - targetEnd. Note: the end pointers are *after* the last item: e.g. - *(sourceEnd - 1) is the last item. - - The return result indicates whether the conversion was successful, - and if not, whether the problem was in the source or target buffers. - (Only the first encountered problem is indicated.) - - After the conversion, *sourceStart and *targetStart are both - updated to point to the end of last text successfully converted in - the respective buffers. - - Input parameters: - sourceStart - pointer to a pointer to the source buffer. - The contents of this are modified on return so that - it points at the next thing to be converted. - targetStart - similarly, pointer to pointer to the target buffer. - sourceEnd, targetEnd - respectively pointers to the ends of the - two buffers, for overflow checking only. - - These conversion functions take a ConversionFlags argument. When this - flag is set to strict, both irregular sequences and isolated surrogates - will cause an error. When the flag is set to lenient, both irregular - sequences and isolated surrogates are converted. - - Whether the flag is strict or lenient, all illegal sequences will cause - an error return. This includes sequences such as: , , - or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code - must check for illegal sequences. - - When the flag is set to lenient, characters over 0x10FFFF are converted - to the replacement character; otherwise (when the flag is set to strict) - they constitute an error. - - Output parameters: - The value "sourceIllegal" is returned from some routines if the input - sequence is malformed. When "sourceIllegal" is returned, the source - value will point to the illegal value that caused the problem. E.g., - in UTF-8 when a sequence is malformed, it points to the start of the - malformed sequence. - - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Fixes & updates, Sept 2001. - ------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------- - The following 4 definitions are compiler-specific. - The C standard does not guarantee that wchar_t has at least - 16 bits, so wchar_t is no less portable than unsigned short! - All should be unsigned values to avoid sign extension during - bit mask & shift operations. ------------------------------------------------------------------------- */ - -typedef unsigned long UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ -typedef unsigned char Boolean; /* 0 or 1 */ - -/* Some fundamental constants */ -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_MAX_BMP (UTF32)0x0000FFFF -#define UNI_MAX_UTF16 (UTF32)0x0010FFFF -#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF -#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF - -typedef enum { - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; - -typedef enum { - strictConversion = 0, - lenientConversion -} ConversionFlags; - -/* This is for C++ and does no harm in C */ -#ifdef __cplusplus -extern "C" { -#endif - - ConversionResult ConvertUTF8toUTF16( - const UTF8 **sourceStart, const UTF8 *sourceEnd, - UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); - - ConversionResult ConvertUTF16toUTF8( - const UTF16 **sourceStart, const UTF16 *sourceEnd, - UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); - - ConversionResult ConvertUTF8toUTF32( - const UTF8 **sourceStart, const UTF8 *sourceEnd, - UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); - - ConversionResult ConvertUTF32toUTF8( - const UTF32 **sourceStart, const UTF32 *sourceEnd, - UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); - - ConversionResult ConvertUTF16toUTF32( - const UTF16 **sourceStart, const UTF16 *sourceEnd, - UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); - - ConversionResult ConvertUTF32toUTF16( - const UTF32 **sourceStart, const UTF32 *sourceEnd, - UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); - - Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); - -#ifdef __cplusplus -} -#endif - -/* --------------------------------------------------------------------- */ diff --git a/engines/wintermute/utils/PathUtil.cpp b/engines/wintermute/utils/PathUtil.cpp deleted file mode 100644 index 7fa06cf682..0000000000 --- a/engines/wintermute/utils/PathUtil.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "common/file.h" -#include "PathUtil.h" -#include "StringUtil.h" - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::unifySeparators(const AnsiString &path) { - AnsiString newPath = path; - - AnsiString::iterator it; - for (it = newPath.begin(); it != newPath.end(); it++) { - if (*it == '\\') *it = '/'; - } - 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 (!StringUtil::endsWith(newPath1, "/", true) && !StringUtil::startsWith(newPath2, "/", true)) - newPath1 += "/"; - - return newPath1 + newPath2; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getDirectoryName(const AnsiString &path) { - AnsiString newPath = unifySeparators(path); - - //size_t pos = newPath.find_last_of(L'/'); - Common::String filename = getFileName(path); - return Common::String(path.c_str(), path.size() - filename.size()); - //if (pos == AnsiString::npos) return ""; - //else return newPath.substr(0, pos + 1); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getFileName(const AnsiString &path) { - AnsiString newPath = unifySeparators(path); - - //size_t pos = newPath.find_last_of(L'/'); TODO REMOVE. - Common::String lastPart = Common::lastPathComponent(path, '/'); - if (lastPart[lastPart.size() - 1 ] != '/') - return lastPart; - else - return path; - //if (pos == AnsiString::npos) return path; - //else return newPath.substr(pos + 1); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getFileNameWithoutExtension(const AnsiString &path) { - AnsiString fileName = getFileName(path); - - //size_t pos = fileName.find_last_of('.'); //TODO REMOVE! - // TODO: Prettify this. - Common::String extension = Common::lastPathComponent(path, '.'); - Common::String filename = Common::String(path.c_str(), path.size() - extension.size()); - return filename; - //if (pos == AnsiString::npos) return fileName; - //else return fileName.substr(0, pos); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getExtension(const AnsiString &path) { - AnsiString fileName = getFileName(path); - - //size_t pos = fileName.find_last_of('.'); - return Common::lastPathComponent(path, '.'); - //if (pos == AnsiString::npos) return ""; - //else return fileName.substr(pos); -} - - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getSafeLogFileName() { - AnsiString logFileName = getUserDirectory(); - -/*#ifdef __WIN32__ - char moduleName[MAX_PATH_LENGTH]; - ::GetModuleFileName(NULL, moduleName, MAX_PATH_LENGTH); - - AnsiString fileName = GetFileNameWithoutExtension(moduleName) + ".log"; - fileName = Combine("/Wintermute Engine/Logs/", fileName); - logFileName = Combine(logFileName, fileName); - -#else*/ - // !PORTME - logFileName = combine(logFileName, "/Wintermute Engine/wme.log"); -//#endif - - createDirectory(getDirectoryName(logFileName)); - return logFileName; -} - -////////////////////////////////////////////////////////////////////////// -bool PathUtil::createDirectory(const AnsiString &path) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool PathUtil::matchesMask(const AnsiString &fileName, const AnsiString &mask) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool PathUtil::fileExists(const AnsiString &fileName) { - warning("PathUtil::FileExists(%s)", fileName.c_str()); - - Common::File stream; - - stream.open(fileName.c_str()); - bool ret = stream.isOpen(); - stream.close(); - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getUserDirectory() { - warning("PathUtil::GetUserDirectory - stubbed"); - AnsiString userDir = "./"; -#if 0 -#ifdef __WIN32__ - char buffer[MAX_PATH_LENGTH]; - buffer[0] = '\0'; - LPITEMIDLIST pidl = NULL; - LPMALLOC pMalloc; - if (DID_SUCCEED(SHGetMalloc(&pMalloc))) { - SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl); - if (pidl) { - SHGetPathFromIDList(pidl, buffer); - } - pMalloc->Free(pidl); - userDir = AnsiString(buffer); - } -#elif __MACOSX__ - FSRef fileRef; - OSStatus error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef); - if (error == noErr) { - char buffer[MAX_PATH_LENGTH]; - error = FSRefMakePath(&fileRef, (UInt8 *)buffer, sizeof(buffer)); - if (error == noErr) - userDir = buffer; - - } -#elif __IPHONEOS__ - char path[MAX_PATH_LENGTH]; - IOS_GetDataDir(path); - userDir = AnsiString(path); -#endif -#endif // 0 - return userDir; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/utils/PathUtil.h b/engines/wintermute/utils/PathUtil.h deleted file mode 100644 index 139ce89ddd..0000000000 --- a/engines/wintermute/utils/PathUtil.h +++ /dev/null @@ -1,56 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/platform_osystem.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); - static bool createDirectory(const AnsiString &path); - static bool matchesMask(const AnsiString &fileName, const AnsiString &mask); - - static bool fileExists(const AnsiString &fileName); - - static AnsiString getSafeLogFileName(); - static AnsiString getUserDirectory(); -}; - -} // end of namespace WinterMute - -#endif // WINTERMUTE_PATHUTILS_H diff --git a/engines/wintermute/utils/StringUtil.cpp b/engines/wintermute/utils/StringUtil.cpp deleted file mode 100644 index 303e7b1131..0000000000 --- a/engines/wintermute/utils/StringUtil.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "common/tokenizer.h" -#include "StringUtil.h" -#include "ConvertUTF.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 - static bool hasWarned = false; - if (!hasWarned) { - hasWarned = true; - warning("StringUtil::AnsiToWide - WideString not supported yet"); - } - /*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 - static bool hasWarned = false; - if (!hasWarned) { - hasWarned = true; - warning("StringUtil::WideToAnsi - WideString not supported yet"); - } - /* 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::startsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) { - /* size_t strLength = str.size(); - size_t patternLength = pattern.size(); - - if (strLength < patternLength || patternLength == 0) - return false; - - AnsiString startPart = str.substr(0, patternLength); - - if (ignoreCase) return CompareNoCase(startPart, pattern); - else return (startPart == pattern);*/ - if (!ignoreCase) - return str.hasPrefix(pattern); - else { - size_t strLength = str.size(); - size_t patternLength = pattern.size(); - - if (strLength < patternLength || patternLength == 0) - return false; - - AnsiString startPart(str.c_str(), patternLength); - uint32 likeness = startPart.compareToIgnoreCase(pattern.c_str()); - return (likeness == 0); - } -} - -////////////////////////////////////////////////////////////////////////// -bool StringUtil::endsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) { - /* size_t strLength = str.size(); // TODO: Remove - size_t patternLength = pattern.size(); - - if (strLength < patternLength || patternLength == 0) - return false; - - AnsiString endPart = str.substr(strLength - patternLength, patternLength); - - if (ignoreCase) return CompareNoCase(endPart, pattern); - else return (endPart == pattern);*/ - if (!ignoreCase) { - return str.hasSuffix(pattern); - } else { - size_t strLength = str.size(); - size_t patternLength = pattern.size(); - - if (strLength < patternLength || patternLength == 0) - return false; - - Common::String endPart(str.c_str() + (strLength - patternLength), patternLength); - uint32 likeness = str.compareToIgnoreCase(pattern.c_str()); - return (likeness != 0); - } -} - -////////////////////////////////////////////////////////////////////////// -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; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::replace(const AnsiString &str, const AnsiString &from, const AnsiString &to) { - if (from.empty() || from == to) return str; - - AnsiString result = str; - /*size_t pos = 0;*/ - - while (result.contains(from)) { - const char *startPtr = strstr(result.c_str(), from.c_str()); - uint32 index = startPtr - result.c_str(); - - Common::String tail(result.c_str() + index + to.size()); - result = Common::String(result.c_str(), index); - result += to; - result += tail; - - /* pos = result.find(from, pos); - if (pos == result.npos) break; - - result.replace(pos, from.size(), to); - pos += to.size();*/ - } - - return result; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::trim(const AnsiString &str, bool fromLeft, bool fromRight, const AnsiString &chars) { - AnsiString trimmedStr = str; - - if (fromRight) { - //trimmedStr.erase(trimmedStr.find_last_not_of(chars) + 1); // TODO - warning("fromRight-trim not implemented yet, %s", chars.c_str()); - } - if (fromLeft) { - uint32 lastOf = lastIndexOf(str, chars, 0); - trimmedStr = Common::String(trimmedStr.c_str() + lastOf); - //trimmedStr.erase(0, trimmedStr.find_first_not_of(chars)); - } - return trimmedStr; -} - -////////////////////////////////////////////////////////////////////////// -int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) { - /*size_t pos = str.find(toFind, startFrom); - if (pos == str.npos) return -1; - else return pos;*/ - const char *index = strstr(str.c_str(), toFind.c_str()); - if (index == NULL) - return -1; - else - return index - str.c_str(); -} - -////////////////////////////////////////////////////////////////////////// -int StringUtil::lastIndexOf(const WideString &str, const WideString &toFind, size_t startFrom) { - /*size_t pos = str.rfind(toFind, startFrom); - if (pos == str.npos) return -1; - else return pos;*/ - int32 lastIndex = -1; - bool found = false; - for (size_t i = startFrom; i < str.size(); i++) { - found = false; - for (size_t j = 0; j < toFind.size(); j++) { - if (str[i + j] != toFind[j]) { - found = false; - break; - } else { - found = true; - } - } - if (found) - lastIndex = i; - } - return lastIndex; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::toString(size_t val) { - return Common::String::format("%u", (uint32)val); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::toString(int val) { - return Common::String::format("%d", val); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::toString(float val) { - return Common::String::format("%f", val); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::toString(double val) { - return Common::String::format("%f", val); -} - - -////////////////////////////////////////////////////////////////////////// -void StringUtil::split(const AnsiString &list, const AnsiString &delimiters, AnsiStringArray &result, bool keepEmptyItems) { - result.clear(); -//TODO: Verify this, wrt keepEmptyItems. - Common::StringTokenizer tokenizer(list.c_str(), delimiters.c_str()); - //typedef boost::char_separator separator_t; - //typedef boost::tokenizer tokenizer_t; - - //separator_t del(delimiters.c_str(), "", keepEmptyItems ? boost::keep_empty_tokens : boost::drop_empty_tokens); - //tokenizer_t tokens(list, del); - while (!tokenizer.empty()) { - Common::String copy(tokenizer.nextToken().c_str()); - result.push_back(copy); - } -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/utils/StringUtil.h b/engines/wintermute/utils/StringUtil.h deleted file mode 100644 index bd1b71f405..0000000000 --- a/engines/wintermute/utils/StringUtil.h +++ /dev/null @@ -1,66 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-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/platform_osystem.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 startsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase = false); - static bool endsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase = false); - - static bool isUtf8BOM(const byte *buffer, uint32 bufferSize); - - static AnsiString replace(const AnsiString &str, const AnsiString &from, const AnsiString &to); - static AnsiString trim(const AnsiString &str, bool fromLeft = true, bool fromRight = true, const AnsiString &chars = " \n\r\t"); - - static int indexOf(const WideString &str, const WideString &toFind, size_t startFrom); - static int lastIndexOf(const WideString &str, const WideString &toFind, size_t startFrom); - - static AnsiString toString(size_t val); - static AnsiString toString(int val); - static AnsiString toString(float val); - static AnsiString toString(double val); - - static void split(const AnsiString &list, const AnsiString &delimiters, AnsiStringArray &result, bool keepEmptyItems = false); -}; - -} // end of namespace WinterMute - -#endif // WINTERMUTE_STRINGUTIL_H diff --git a/engines/wintermute/utils/convert_utf.cpp b/engines/wintermute/utils/convert_utf.cpp new file mode 100644 index 0000000000..db0c0fa9f9 --- /dev/null +++ b/engines/wintermute/utils/convert_utf.cpp @@ -0,0 +1,612 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "engines/wintermute/utils/convert_utf.h" +#ifdef CVTUTF_DEBUG +#include +#endif + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32 *source = *sourceStart; + UTF16 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; + break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; + break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16 *source = *sourceStart; + UTF32 *target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; + break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG + if (result == sourceIllegal) { + fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + fflush(stderr); + } +#endif + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL + }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF8( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16 *source = *sourceStart; + UTF8 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { + bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { + bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { + bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { + bytesToWrite = 4; + } else { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 3: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 2: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 1: + *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source + length; + switch (length) { + default: + return false; + /* Everything else falls through when "true"... */ + case 4: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: + if ((a = (*--srcptr)) > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: + if (a < 0xA0) return false; + break; + case 0xED: + if (a > 0x9F) return false; + break; + case 0xF0: + if (a < 0x90) return false; + break; + case 0xF4: + if (a > 0x8F) return false; + break; + default: + if (a < 0x80) return false; + } + + case 1: + if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source] + 1; + if (source + length > sourceEnd) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8 *source = *sourceStart; + UTF16 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; + break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead + 1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + case 4: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + case 3: + ch += *source++; + ch <<= 6; + case 2: + ch += *source++; + ch <<= 6; + case 1: + ch += *source++; + ch <<= 6; + case 0: + ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead + 1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32 *source = *sourceStart; + UTF8 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { + bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { + bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { + bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { + bytesToWrite = 4; + } else { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 3: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 2: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 1: + *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF32( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8 *source = *sourceStart; + UTF32 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; + break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead + 1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: + ch += *source++; + ch <<= 6; + case 4: + ch += *source++; + ch <<= 6; + case 3: + ch += *source++; + ch <<= 6; + case 2: + ch += *source++; + ch <<= 6; + case 1: + ch += *source++; + ch <<= 6; + case 0: + ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up the source pointer! */ + result = targetExhausted; + break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */ diff --git a/engines/wintermute/utils/convert_utf.h b/engines/wintermute/utils/convert_utf.h new file mode 100644 index 0000000000..03a8bb2bae --- /dev/null +++ b/engines/wintermute/utils/convert_utf.h @@ -0,0 +1,149 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: , , + or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned long UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + + ConversionResult ConvertUTF8toUTF16( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF16toUTF8( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF8toUTF32( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF32toUTF8( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF16toUTF32( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); + + ConversionResult ConvertUTF32toUTF16( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); + + Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +#ifdef __cplusplus +} +#endif + +/* --------------------------------------------------------------------- */ diff --git a/engines/wintermute/utils/crc.cpp b/engines/wintermute/utils/crc.cpp index 0bce1c4c51..933857e066 100644 --- a/engines/wintermute/utils/crc.cpp +++ b/engines/wintermute/utils/crc.cpp @@ -15,7 +15,7 @@ * expressed or implied by its publication or distribution. **********************************************************************/ -#include "crc.h" +#include "engines/wintermute/utils/crc.h" /* diff --git a/engines/wintermute/utils/path_util.cpp b/engines/wintermute/utils/path_util.cpp new file mode 100644 index 0000000000..6b6b2d6b96 --- /dev/null +++ b/engines/wintermute/utils/path_util.cpp @@ -0,0 +1,196 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#include "common/file.h" +#include "engines/wintermute/utils/path_util.h" +#include "engines/wintermute/utils/string_util.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::unifySeparators(const AnsiString &path) { + AnsiString newPath = path; + + AnsiString::iterator it; + for (it = newPath.begin(); it != newPath.end(); it++) { + if (*it == '\\') *it = '/'; + } + 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 (!StringUtil::endsWith(newPath1, "/", true) && !StringUtil::startsWith(newPath2, "/", true)) + newPath1 += "/"; + + return newPath1 + newPath2; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getDirectoryName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + + //size_t pos = newPath.find_last_of(L'/'); + Common::String filename = getFileName(path); + return Common::String(path.c_str(), path.size() - filename.size()); + //if (pos == AnsiString::npos) return ""; + //else return newPath.substr(0, pos + 1); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getFileName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + + //size_t pos = newPath.find_last_of(L'/'); TODO REMOVE. + Common::String lastPart = Common::lastPathComponent(path, '/'); + if (lastPart[lastPart.size() - 1 ] != '/') + return lastPart; + else + return path; + //if (pos == AnsiString::npos) return path; + //else return newPath.substr(pos + 1); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getFileNameWithoutExtension(const AnsiString &path) { + AnsiString fileName = getFileName(path); + + //size_t pos = fileName.find_last_of('.'); //TODO REMOVE! + // TODO: Prettify this. + Common::String extension = Common::lastPathComponent(path, '.'); + Common::String filename = Common::String(path.c_str(), path.size() - extension.size()); + return filename; + //if (pos == AnsiString::npos) return fileName; + //else return fileName.substr(0, pos); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getExtension(const AnsiString &path) { + AnsiString fileName = getFileName(path); + + //size_t pos = fileName.find_last_of('.'); + return Common::lastPathComponent(path, '.'); + //if (pos == AnsiString::npos) return ""; + //else return fileName.substr(pos); +} + + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getSafeLogFileName() { + AnsiString logFileName = getUserDirectory(); + +/*#ifdef __WIN32__ + char moduleName[MAX_PATH_LENGTH]; + ::GetModuleFileName(NULL, moduleName, MAX_PATH_LENGTH); + + AnsiString fileName = GetFileNameWithoutExtension(moduleName) + ".log"; + fileName = Combine("/Wintermute Engine/Logs/", fileName); + logFileName = Combine(logFileName, fileName); + +#else*/ + // !PORTME + logFileName = combine(logFileName, "/Wintermute Engine/wme.log"); +//#endif + + createDirectory(getDirectoryName(logFileName)); + return logFileName; +} + +////////////////////////////////////////////////////////////////////////// +bool PathUtil::createDirectory(const AnsiString &path) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool PathUtil::matchesMask(const AnsiString &fileName, const AnsiString &mask) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool PathUtil::fileExists(const AnsiString &fileName) { + warning("PathUtil::FileExists(%s)", fileName.c_str()); + + Common::File stream; + + stream.open(fileName.c_str()); + bool ret = stream.isOpen(); + stream.close(); + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getUserDirectory() { + warning("PathUtil::GetUserDirectory - stubbed"); + AnsiString userDir = "./"; +#if 0 +#ifdef __WIN32__ + char buffer[MAX_PATH_LENGTH]; + buffer[0] = '\0'; + LPITEMIDLIST pidl = NULL; + LPMALLOC pMalloc; + if (DID_SUCCEED(SHGetMalloc(&pMalloc))) { + SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl); + if (pidl) { + SHGetPathFromIDList(pidl, buffer); + } + pMalloc->Free(pidl); + userDir = AnsiString(buffer); + } +#elif __MACOSX__ + FSRef fileRef; + OSStatus error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef); + if (error == noErr) { + char buffer[MAX_PATH_LENGTH]; + error = FSRefMakePath(&fileRef, (UInt8 *)buffer, sizeof(buffer)); + if (error == noErr) + userDir = buffer; + + } +#elif __IPHONEOS__ + char path[MAX_PATH_LENGTH]; + IOS_GetDataDir(path); + userDir = AnsiString(path); +#endif +#endif // 0 + return userDir; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/utils/path_util.h b/engines/wintermute/utils/path_util.h new file mode 100644 index 0000000000..139ce89ddd --- /dev/null +++ b/engines/wintermute/utils/path_util.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_PATHUTILS_H +#define WINTERMUTE_PATHUTILS_H + +#include "engines/wintermute/platform_osystem.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); + static bool createDirectory(const AnsiString &path); + static bool matchesMask(const AnsiString &fileName, const AnsiString &mask); + + static bool fileExists(const AnsiString &fileName); + + static AnsiString getSafeLogFileName(); + static AnsiString getUserDirectory(); +}; + +} // end of namespace WinterMute + +#endif // WINTERMUTE_PATHUTILS_H diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp new file mode 100644 index 0000000000..c3fcb09f1d --- /dev/null +++ b/engines/wintermute/utils/string_util.cpp @@ -0,0 +1,381 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/dcgf.h" +#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 + static bool hasWarned = false; + if (!hasWarned) { + hasWarned = true; + warning("StringUtil::AnsiToWide - WideString not supported yet"); + } + /*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 + static bool hasWarned = false; + if (!hasWarned) { + hasWarned = true; + warning("StringUtil::WideToAnsi - WideString not supported yet"); + } + /* 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::startsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) { + /* size_t strLength = str.size(); + size_t patternLength = pattern.size(); + + if (strLength < patternLength || patternLength == 0) + return false; + + AnsiString startPart = str.substr(0, patternLength); + + if (ignoreCase) return CompareNoCase(startPart, pattern); + else return (startPart == pattern);*/ + if (!ignoreCase) + return str.hasPrefix(pattern); + else { + size_t strLength = str.size(); + size_t patternLength = pattern.size(); + + if (strLength < patternLength || patternLength == 0) + return false; + + AnsiString startPart(str.c_str(), patternLength); + uint32 likeness = startPart.compareToIgnoreCase(pattern.c_str()); + return (likeness == 0); + } +} + +////////////////////////////////////////////////////////////////////////// +bool StringUtil::endsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) { + /* size_t strLength = str.size(); // TODO: Remove + size_t patternLength = pattern.size(); + + if (strLength < patternLength || patternLength == 0) + return false; + + AnsiString endPart = str.substr(strLength - patternLength, patternLength); + + if (ignoreCase) return CompareNoCase(endPart, pattern); + else return (endPart == pattern);*/ + if (!ignoreCase) { + return str.hasSuffix(pattern); + } else { + size_t strLength = str.size(); + size_t patternLength = pattern.size(); + + if (strLength < patternLength || patternLength == 0) + return false; + + Common::String endPart(str.c_str() + (strLength - patternLength), patternLength); + uint32 likeness = str.compareToIgnoreCase(pattern.c_str()); + return (likeness != 0); + } +} + +////////////////////////////////////////////////////////////////////////// +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; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::replace(const AnsiString &str, const AnsiString &from, const AnsiString &to) { + if (from.empty() || from == to) return str; + + AnsiString result = str; + /*size_t pos = 0;*/ + + while (result.contains(from)) { + const char *startPtr = strstr(result.c_str(), from.c_str()); + uint32 index = startPtr - result.c_str(); + + Common::String tail(result.c_str() + index + to.size()); + result = Common::String(result.c_str(), index); + result += to; + result += tail; + + /* pos = result.find(from, pos); + if (pos == result.npos) break; + + result.replace(pos, from.size(), to); + pos += to.size();*/ + } + + return result; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::trim(const AnsiString &str, bool fromLeft, bool fromRight, const AnsiString &chars) { + AnsiString trimmedStr = str; + + if (fromRight) { + //trimmedStr.erase(trimmedStr.find_last_not_of(chars) + 1); // TODO + warning("fromRight-trim not implemented yet, %s", chars.c_str()); + } + if (fromLeft) { + uint32 lastOf = lastIndexOf(str, chars, 0); + trimmedStr = Common::String(trimmedStr.c_str() + lastOf); + //trimmedStr.erase(0, trimmedStr.find_first_not_of(chars)); + } + return trimmedStr; +} + +////////////////////////////////////////////////////////////////////////// +int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) { + /*size_t pos = str.find(toFind, startFrom); + if (pos == str.npos) return -1; + else return pos;*/ + const char *index = strstr(str.c_str(), toFind.c_str()); + if (index == NULL) + return -1; + else + return index - str.c_str(); +} + +////////////////////////////////////////////////////////////////////////// +int StringUtil::lastIndexOf(const WideString &str, const WideString &toFind, size_t startFrom) { + /*size_t pos = str.rfind(toFind, startFrom); + if (pos == str.npos) return -1; + else return pos;*/ + int32 lastIndex = -1; + bool found = false; + for (size_t i = startFrom; i < str.size(); i++) { + found = false; + for (size_t j = 0; j < toFind.size(); j++) { + if (str[i + j] != toFind[j]) { + found = false; + break; + } else { + found = true; + } + } + if (found) + lastIndex = i; + } + return lastIndex; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::toString(size_t val) { + return Common::String::format("%u", (uint32)val); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::toString(int val) { + return Common::String::format("%d", val); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::toString(float val) { + return Common::String::format("%f", val); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::toString(double val) { + return Common::String::format("%f", val); +} + + +////////////////////////////////////////////////////////////////////////// +void StringUtil::split(const AnsiString &list, const AnsiString &delimiters, AnsiStringArray &result, bool keepEmptyItems) { + result.clear(); +//TODO: Verify this, wrt keepEmptyItems. + Common::StringTokenizer tokenizer(list.c_str(), delimiters.c_str()); + //typedef boost::char_separator separator_t; + //typedef boost::tokenizer tokenizer_t; + + //separator_t del(delimiters.c_str(), "", keepEmptyItems ? boost::keep_empty_tokens : boost::drop_empty_tokens); + //tokenizer_t tokens(list, del); + while (!tokenizer.empty()) { + Common::String copy(tokenizer.nextToken().c_str()); + result.push_back(copy); + } +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/utils/string_util.h b/engines/wintermute/utils/string_util.h new file mode 100644 index 0000000000..bd1b71f405 --- /dev/null +++ b/engines/wintermute/utils/string_util.h @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_STRINGUTIL_H +#define WINTERMUTE_STRINGUTIL_H + +#include "engines/wintermute/platform_osystem.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 startsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase = false); + static bool endsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase = false); + + static bool isUtf8BOM(const byte *buffer, uint32 bufferSize); + + static AnsiString replace(const AnsiString &str, const AnsiString &from, const AnsiString &to); + static AnsiString trim(const AnsiString &str, bool fromLeft = true, bool fromRight = true, const AnsiString &chars = " \n\r\t"); + + static int indexOf(const WideString &str, const WideString &toFind, size_t startFrom); + static int lastIndexOf(const WideString &str, const WideString &toFind, size_t startFrom); + + static AnsiString toString(size_t val); + static AnsiString toString(int val); + static AnsiString toString(float val); + static AnsiString toString(double val); + + static void split(const AnsiString &list, const AnsiString &delimiters, AnsiStringArray &result, bool keepEmptyItems = false); +}; + +} // end of namespace WinterMute + +#endif // WINTERMUTE_STRINGUTIL_H diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp index 1735732185..e77f35a0e8 100644 --- a/engines/wintermute/utils/utils.cpp +++ b/engines/wintermute/utils/utils.cpp @@ -27,11 +27,11 @@ */ #include "engines/wintermute/dcgf.h" -#include "utils.h" +#include "engines/wintermute/utils/utils.h" #include "engines/wintermute/platform_osystem.h" #include "engines/wintermute/wintypes.h" -#include "PathUtil.h" -#include "engines/wintermute/base/BGame.h" +#include "engines/wintermute/utils/path_util.h" +#include "engines/wintermute/base/base_game.h" #include "common/str.h" #include "common/textconsole.h" #include "engines/wintermute/wintermute.h" diff --git a/engines/wintermute/utils/utils.h b/engines/wintermute/utils/utils.h index 14b8f4aa96..c8ca2e121c 100644 --- a/engines/wintermute/utils/utils.h +++ b/engines/wintermute/utils/utils.h @@ -30,7 +30,7 @@ #define WINTERMUTE_UTILS_H #include "engines/wintermute/wintypes.h" -#include "engines/wintermute/math/Rect32.h" +#include "engines/wintermute/math/rect32.h" namespace WinterMute { diff --git a/engines/wintermute/video/VidPlayer.cpp b/engines/wintermute/video/VidPlayer.cpp deleted file mode 100644 index 93f3196eee..0000000000 --- a/engines/wintermute/video/VidPlayer.cpp +++ /dev/null @@ -1,470 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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 "VidPlayer.h" - -//#pragma comment(lib, "vfw32.lib") - -namespace WinterMute { - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////// -CVidPlayer::CVidPlayer(CBGame *inGame): CBBase(inGame) { - SetDefaults(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::SetDefaults() { - _playing = false; - - /* _aviFile = NULL; - - _audioStream = NULL; - _audioFormat = NULL; - - _videoStream = NULL; - _videoFormat = NULL; - _videoPGF = NULL;*/ - _videoEndTime = 0; - - //_sound = NULL; - _soundAvailable = false; - - //_vidRenderer = NULL; - - _startTime = 0; - _totalVideoTime = 0; - - //_lastSample = -1; - - //_targetFormat = NULL; - - _playPosX = _playPosY = 0; - _playZoom = 0.0f; - - _filename = NULL; - - _slowRendering = false; - - _currentSubtitle = 0; - _showSubtitle = false; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -CVidPlayer::~CVidPlayer() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::cleanup() { -#if 0 - if (_sound) _sound->Stop(); - if (_videoPGF) AVIStreamGetFrameClose(_videoPGF); - _videoPGF = NULL; - - _playing = false; - - - if (_aviFile) AVIFileRelease(m_AviFile); - - if (_audioStream) AVIStreamRelease(m_AudioStream); - if (_videoStream) AVIStreamRelease(m_VideoStream); - - if (_audioFormat) delete [](byte *)m_AudioFormat; - if (_videoFormat) delete [](byte *)m_VideoFormat; - if (_targetFormat) delete [](byte *)m_TargetFormat; - - SAFE_DELETE(_sound); - SAFE_DELETE(_vidRenderer); - - SAFE_DELETE_ARRAY(_filename); - - for (int i = 0; i < _subtitles.getSize(); i++) delete _subtitles[i]; - _subtitles.removeAll(); - - return SetDefaults(); -#endif - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::initialize(const char *inFilename, const char *SubtitleFile) { -#if 0 - cleanup(); - - char Filename[MAX_PATH_LENGTH]; - _gameRef->_fileManager->GetFullPath(inFilename, filename); - - // open file - if (AVIFileOpen(&_aviFile, Filename, OF_READ, NULL) != 0) { - _gameRef->LOG(0, "Error opening AVI file '%s'", filename); - return STATUS_FAILED; - } - - // get video stream - if (AVIFileGetStream(_aviFile, &_videoStream, streamtypeVIDEO, 0) != 0) { - _gameRef->LOG(0, "Error finding video stream in AVI file '%s'", filename); - return STATUS_FAILED; - } - _totalVideoTime = AVIStreamEndTime(_videoStream); - - // get audio stream - if (_gameRef->m_SoundMgr->_soundAvailable && AVIFileGetStream(_aviFile, &_audioStream, streamtypeAUDIO, 0) == 0) - _soundAvailable = true; - else - _soundAvailable = false; - - - LONG Size; - - // get video format - if (AVIStreamReadFormat(m_VideoStream, 0, NULL, &Size)) { - _gameRef->LOG(0, "Error obtaining video stream format in AVI file '%s'", filename); - return STATUS_FAILED; - } - _videoFormat = (LPBITMAPINFO)new BYTE[Size]; - AVIStreamReadFormat(m_VideoStream, 0, m_VideoFormat, &Size); - - // initialize optimal target format - m_TargetFormat = (LPBITMAPV4HEADER)new BYTE[max(Size, sizeof(BITMAPV4HEADER))]; - memset(m_TargetFormat, 0, sizeof(BITMAPV4HEADER)); - memcpy(m_TargetFormat, m_VideoFormat, Size); - m_TargetFormat->bV4Size = max(Size, sizeof(BITMAPV4HEADER)); - - m_TargetFormat->bV4BitCount = 24; - m_TargetFormat->bV4V4Compression = BI_RGB; - - if (_gameRef->m_UseD3D) - m_VidRenderer = new CVidRendererD3D(_gameRef); - else - m_VidRenderer = new CVidRendererDD(_gameRef); - - if (!m_VidRenderer || DID_FAIL(m_VidRenderer->Initialize(m_VideoFormat, m_TargetFormat))) { - _gameRef->LOG(0, "Error initializing video renderer for AVI file '%s'", filename); - SAFE_DELETE(m_VidRenderer); - return STATUS_FAILED; - } - - - // create sound buffer - bool res; - - if (_soundAvailable) { - _sound = new CBSoundAVI(_gameRef); - if (DID_FAIL(res = _sound->InitializeBuffer(_audioStream))) { - SAFE_DELETE(_sound); - _soundAvailable = false; - _gameRef->LOG(res, "Error initializing sound buffer for AVI file '%s'", filename); - } - } - - if (_gameRef->_videoSubtitles) LoadSubtitles(inFilename, SubtitleFile); - - _filename = new char[strlen(filename) + 1]; - if (_filename) strcpy(_filename, filename); -#endif - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::update() { -#if 0 - if (!m_Playing) return STATUS_OK; - - bool res; - - if (_soundAvailable && m_Sound) { - res = _sound->update(); - if (DID_FAIL(res)) return res; - } - - - DWORD CurrentTime; // current playing time (in ms) - /* - if(m_SoundAvailable && m_Sound){ - CurrentTime = m_Sound->GetPosition(); // in samples - CurrentTime /= (m_Sound->m_Format.wf.nSamplesPerSec / 1000); - - if(!m_Sound->IsPlaying()) CurrentTime = m_TotalVideoTime; - } - else - CurrentTime = timeGetTime() - m_StartTime; - */ - CurrentTime = timeGetTime() - _startTime; - - if (CurrentTime >= _totalVideoTime) { - Stop(); - return STATUS_OK; - } - - - // get and render frame - DWORD sample = AVIStreamTimeToSample(_videoStream, CurrentTime); - if (sample != _lastSample) { - _lastSample = sample; - - // process subtitles - _showSubtitle = false; - while (_currentSubtitle < _subtitles.getSize()) { - int End = _subtitles[_currentSubtitle]->m_EndFrame; - - bool NextFrameOK = (_currentSubtitle < _subtitles.getSize() - 1 && _subtitles[_currentSubtitle + 1]->_startFrame <= sample); - - if (sample > End) { - if (NextFrameOK) { - _currentSubtitle++; - } else { - _showSubtitle = (End == 0); - break; - } - } else { - _showSubtitle = true; - break; - } - } - - - // render frame - LPBITMAPINFOHEADER FrameData = (LPBITMAPINFOHEADER)AVIStreamGetFrame(m_VideoPGF, sample); - if (FrameData) { - if (_slowRendering) return _vidRenderer->ProcessFrameSlow(FrameData); - else return _vidRenderer->ProcessFrame(FrameData); - } else return STATUS_FAILED; - } else return STATUS_OK; -#endif - return 0; -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::display() { -#if 0 - if (!m_Playing) return STATUS_OK; - - bool res; - if (_vidRenderer) res = _vidRenderer->display(m_PlayPosX, m_PlayPosY, m_PlayZoom); - else res = STATUS_FAILED; - - // display subtitle - if (m_ShowSubtitle) { - CBFont *font = _gameRef->_videoFont ? _gameRef->_videoFont : _gameRef->_systemFont; - int Height = font->GetTextHeight((BYTE *)m_Subtitles[_currentSubtitle]->_text, _gameRef->_renderer->_width); - font->drawText((byte *)_subtitles[m_CurrentSubtitle]->_text, 0, _gameRef->_renderer->_height - Height - 5, _gameRef->_renderer->_width, TAL_CENTER); - } - - return res; -#endif - return 0; -} - - - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::play(TVideoPlayback Type, int X, int Y, bool FreezeMusic) { -#if 0 - if (!_videoStream || !_vidRenderer) return STATUS_FAILED; - - switch (Type) { - case VID_PLAY_POS: - _playZoom = 100.0f; - _playPosX = X; - _playPosY = Y; - break; - - case VID_PLAY_STRETCH: { - float ZoomX = (float)((float)_gameRef->_renderer->m_Width / (float)_videoFormat->bmiHeader.biWidth * 100); - float ZoomY = (float)((float)_gameRef->_renderer->m_Height / (float)_videoFormat->bmiHeader.biHeight * 100); - _playZoom = min(ZoomX, ZoomY); - _playPosX = (_gameRef->_renderer->_width - _videoFormat->bmiHeader.biWidth * (_playZoom / 100)) / 2; - _playPosY = (_gameRef->_renderer->_height - _videoFormat->bmiHeader.biHeight * (_playZoom / 100)) / 2; - } - break; - - case VID_PLAY_CENTER: - _playZoom = 100.0f; - _playPosX = (_gameRef->_renderer->_width - _videoFormat->bmiHeader.biWidth) / 2; - _playPosY = (_gameRef->_renderer->_height - _videoFormat->bmiHeader.biHeight) / 2; - break; - } - - _targetFormat->bV4BitCount = 24; - _targetFormat->bV4V4Compression = BI_RGB; - - - _videoPGF = AVIStreamGetFrameOpen(_videoStream, (LPBITMAPINFOHEADER)m_TargetFormat); - if (!_videoPGF) { - _videoPGF = AVIStreamGetFrameOpen(_videoStream, NULL); - if (!_videoPGF) { - _gameRef->LOG(0, "Error: Unsupported AVI format (file '%s')", m_Filename); - cleanup(); - return STATUS_FAILED; - } else { - _gameRef->LOG(0, "Performance warning: non-optimal AVI format, using generic (i.e. slow) rendering routines (file '%s')", m_Filename); - _slowRendering = true; - } - } else _slowRendering = false; - - // HACK!!! - _slowRendering = true; - - - _currentSubtitle = 0; - - _gameRef->Freeze(FreezeMusic); - - _playing = true; - if (_sound) _sound->Play(); - _startTime = timeGetTime(); -#endif - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::stop() { -#if 0 - if (!_playing) return STATUS_OK; - - cleanup(); - - _gameRef->Unfreeze(); -#endif - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::isPlaying() { - return _playing; -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidPlayer::loadSubtitles(const char *filename, const char *SubtitleFile) { -#if 0 - if (!Filename) return STATUS_OK; - - char NewFile[MAX_PATH_LENGTH]; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char fname[_MAX_FNAME]; - - if (SubtitleFile) { - strcpy(NewFile, SubtitleFile); - } else { - _splitpath(filename, drive, dir, fname, NULL); - _makepath(NewFile, drive, dir, fname, ".SUB"); - } - - DWORD Size; - BYTE *Buffer = _gameRef->m_FileManager->readWholeFile(NewFile, &Size, false); - if (Buffer == NULL) return STATUS_OK; // no subtitles - - - LONG Start, End; - bool InToken; - char *TokenStart; - int TokenLength; - int TokenPos; - int TextLength; - - int Pos = 0; - int LineLength = 0; - while (Pos < Size) { - Start = End = -1; - InToken = false; - TokenPos = -1; - TextLength = 0; - - LineLength = 0; - while (Pos + LineLength < Size && Buffer[Pos + LineLength] != '\n' && Buffer[Pos + LineLength] != '\0') LineLength++; - - int RealLength = LineLength - (Pos + LineLength >= Size ? 0 : 1); - char *Text = new char[RealLength + 1]; - char *line = (char *)&Buffer[Pos]; - - for (int i = 0; i < RealLength; i++) { - if (line[i] == '{') { - if (!InToken) { - InToken = true; - TokenStart = line + i + 1; - TokenLength = 0; - TokenPos++; - } else TokenLength++; - } else if (line[i] == '}') { - if (InToken) { - InToken = false; - char *Token = new char[TokenLength + 1]; - strncpy(Token, TokenStart, TokenLength); - Token[TokenLength] = '\0'; - if (TokenPos == 0) Start = atoi(Token); - else if (TokenPos == 1) End = atoi(Token); - - delete [] Token; - } else { - Text[TextLength] = line[i]; - TextLength++; - } - } else { - if (InToken) { - TokenLength++; - } else { - Text[TextLength] = line[i]; - if (Text[TextLength] == '|') Text[TextLength] = '\n'; - TextLength++; - } - } - } - Text[TextLength] = '\0'; - - if (Start != -1 && TextLength > 0) _subtitles.add(new CVidSubtitle(_gameRef, Text, Start, End)); - - delete [] Text; - - Pos += LineLength + 1; - } - - delete [] Buffer; -#endif - return STATUS_OK; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/video/VidPlayer.h b/engines/wintermute/video/VidPlayer.h deleted file mode 100644 index a44482e4c6..0000000000 --- a/engines/wintermute/video/VidPlayer.h +++ /dev/null @@ -1,93 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_VIDPLAYER_H -#define WINTERMUTE_VIDPLAYER_H - -#include "engines/wintermute/dctypes.h" // Added by ClassView -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "engines/wintermute/base/BBase.h" - -#define MAX_AUDIO_STREAMS 5 -#define MAX_VIDEO_STREAMS 5 - - -namespace WinterMute { - -class CVidPlayer : public CBBase { -public: - bool _showSubtitle; - int _currentSubtitle; - bool loadSubtitles(const char *filename, const char *SubtitleFile); - bool _slowRendering; - bool isPlaying(); - char *_filename; - bool stop(); - bool play(TVideoPlayback Type = VID_PLAY_CENTER, int X = 0, int Y = 0, bool FreezeMusic = true); - uint32 _totalVideoTime; - uint32 _startTime; - //CVidRenderer *_vidRenderer; - //CBSoundAVI *_sound; - bool _soundAvailable; - bool SetDefaults(); - bool _playing; - bool display(); - bool update(); - bool initialize(const char *inFilename, const char *SubtitleFile = NULL); - bool cleanup(); - CVidPlayer(CBGame *inGame); - virtual ~CVidPlayer(); - - /*PAVIFILE _aviFile; - - LONG _lastSample; - - PAVISTREAM _audioStream; - PAVISTREAM _videoStream; - - LPWAVEFORMAT _audioFormat; - - LPBITMAPINFO _videoFormat; - PGETFRAME _videoPGF;*/ - uint32 _videoEndTime; - - int _playPosX; - int _playPosY; - float _playZoom; - - /* LPBITMAPV4HEADER _targetFormat; - - CBArray _subtitles;*/ -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/video/VidTheoraPlayer.cpp b/engines/wintermute/video/VidTheoraPlayer.cpp deleted file mode 100644 index ffb24d22dd..0000000000 --- a/engines/wintermute/video/VidTheoraPlayer.cpp +++ /dev/null @@ -1,850 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/video/VidTheoraPlayer.h" -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/base/BGame.h" -#include "engines/wintermute/base/BFileManager.h" -#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" -#include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/video/decoders/theora_decoder.h" -#include "common/system.h" -//#pragma comment(lib, "libtheora.lib") - -namespace WinterMute { - -IMPLEMENT_PERSISTENT(CVidTheoraPlayer, false) - -////////////////////////////////////////////////////////////////////////// -CVidTheoraPlayer::CVidTheoraPlayer(CBGame *inGame): CBBase(inGame) { - SetDefaults(); -} - -////////////////////////////////////////////////////////////////////////// -void CVidTheoraPlayer::SetDefaults() { - - _file = NULL; - _filename = ""; - _startTime = 0; - _looping = false; - - _freezeGame = false; - _currentTime = 0; - - _state = THEORA_STATE_NONE; - - _videoFrameReady = false; - _audioFrameReady = false; - _videobufTime = 0; - - _playbackStarted = false; - _dontDropFrames = false; - - _texture = NULL; - _alphaImage = NULL; - _alphaFilename = ""; - - _frameRendered = false; - - _seekingKeyframe = false; - _timeOffset = 0.0f; - - _posX = _posY = 0; - _playbackType = VID_PLAY_CENTER; - _playZoom = 0.0f; - - _savedState = THEORA_STATE_NONE; - _savedPos = 0; - _volume = 100; - _theoraDecoder = NULL; -#if 0 - _vorbisStreams = _theoraStreams = 0; - - GenLookupTables(); - - _subtitler = NULL; -#endif -} - -////////////////////////////////////////////////////////////////////////// -CVidTheoraPlayer::~CVidTheoraPlayer(void) { - cleanup(); - - /* SAFE_DELETE_ARRAY(_filename); - SAFE_DELETE_ARRAY(_alphaFilename); - SAFE_DELETE(_texture); - SAFE_DELETE(_alphaImage);*/ -// SAFE_DELETE(_subtitler); -} - -////////////////////////////////////////////////////////////////////////// -void CVidTheoraPlayer::cleanup() { - if (_file) { - _gameRef->_fileManager->closeFile(_file); - _file = NULL; - } - - _surface.free(); - delete _theoraDecoder; - _theoraDecoder = NULL; - delete _alphaImage; - _alphaImage = NULL; - delete _texture; - _texture = NULL; -#if 0 - if (m_Sound) { - _gameRef->m_SoundMgr->RemoveSound(m_Sound); - m_Sound = NULL; - } - - SAFE_DELETE_ARRAY(m_AudioBuf); - m_AudioBufFill = 0; - m_AudioBufSize = 0; -#endif -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::initialize(const Common::String &filename, const Common::String &subtitleFile) { - cleanup(); - - _filename = filename; - _file = _gameRef->_fileManager->openFile(filename, true, false); - if (!_file) return STATUS_FAILED; - - //if (Filename != _filename) CBUtils::setString(&_filename, filename); -#if defined (USE_THEORADEC) - _theoraDecoder = new TheoraDecoder(); -#else - return STATUS_FAILED; -#endif - _theoraDecoder->loadStream(_file); - - if (!_theoraDecoder->isVideoLoaded()) - return STATUS_FAILED; - - _state = THEORA_STATE_PAUSED; - - // Additional setup. - _surface.create(_theoraDecoder->getWidth(), _theoraDecoder->getHeight(), _theoraDecoder->getPixelFormat()); - _texture = new CBSurfaceOSystem(_gameRef); - _texture->create(_theoraDecoder->getWidth(), _theoraDecoder->getHeight()); - _state = THEORA_STATE_PLAYING; - _playZoom = 100; - - return STATUS_OK; -#if 0 - cleanup(); - - _file = _gameRef->_fileManager->openFile(filename); - if (!_file) return STATUS_FAILED; - - if (Filename != _filename) CBUtils::setString(&_filename, filename); - - // start up Ogg stream synchronization layer - ogg_sync_init(&m_OggSyncState); - - // init supporting Vorbis structures needed in header parsing - vorbis_comment_init(&m_VorbisComment); - vorbis_info_init(&m_VorbisInfo); - - // init supporting Theora structures needed in header parsing - theora_comment_init(&m_TheoraComment); - theora_info_init(&m_TheoraInfo); - - - - // Ogg file open; parse the headers - // Only interested in Vorbis/Theora streams - ogg_packet TempOggPacket; - bool IsDone = false; - while (!IsDone) { - int BytesRead = BufferData(&m_OggSyncState); - if (BytesRead == 0) break; - - while (ogg_sync_pageout(&m_OggSyncState, &m_OggPage) > 0) { - ogg_stream_state OggStateTest; - - // is this a mandated initial header? If not, stop parsing - if (!ogg_page_bos(&m_OggPage)) { - // don't leak the page; get it into the appropriate stream - if (m_TheoraStreams) - ogg_stream_pagein(&m_TheoraStreamState, &m_OggPage); - if (m_VorbisStreams) - ogg_stream_pagein(&m_VorbisStreamState, &m_OggPage); - - IsDone = true; - break; - } - - ogg_stream_init(&OggStateTest, ogg_page_serialno(&m_OggPage)); - ogg_stream_pagein(&OggStateTest, &m_OggPage); - ogg_stream_packetout(&OggStateTest, &TempOggPacket); - - // identify the codec: try theora - if (!m_TheoraStreams && theora_decode_header(&m_TheoraInfo, &m_TheoraComment, &TempOggPacket) >= 0) { - // it is theora - memcpy(&m_TheoraStreamState, &OggStateTest, sizeof(OggStateTest)); - m_TheoraStreams = 1; - } else if (!m_VorbisStreams && vorbis_synthesis_headerin(&m_VorbisInfo, &m_VorbisComment, &TempOggPacket) >= 0) { - // it is vorbis - memcpy(&m_VorbisStreamState, &OggStateTest, sizeof(OggStateTest)); - m_VorbisStreams = 1; - } else { - // whatever it is, we don't care about it - ogg_stream_clear(&OggStateTest); - } - } - } - - // we're expecting more header packets - while ((m_TheoraStreams && m_TheoraStreams < 3) || (m_VorbisStreams && m_VorbisStreams < 3)) { - int Ret; - - // look for further theora headers - while (m_TheoraStreams && (m_TheoraStreams < 3) && (Ret = ogg_stream_packetout(&m_TheoraStreamState, &TempOggPacket))) { - if (Ret < 0) { - _gameRef->LOG(0, "Error parsing Theora stream headers; corrupt stream?"); - return STATUS_FAILED; - } - if (theora_decode_header(&m_TheoraInfo, &m_TheoraComment, &TempOggPacket)) { - _gameRef->LOG(0, "Error parsing Theora stream headers; corrupt stream?"); - return STATUS_FAILED; - } - m_TheoraStreams++; - if (m_TheoraStreams == 3) break; - } - - /* look for more vorbis header packets */ - while (m_VorbisStreams && (m_VorbisStreams < 3) && (Ret = ogg_stream_packetout(&m_VorbisStreamState, &TempOggPacket))) { - if (Ret < 0) { - _gameRef->LOG(0, "Error parsing Vorbis stream headers; corrupt stream?"); - return STATUS_FAILED; - } - if (vorbis_synthesis_headerin(&m_VorbisInfo, &m_VorbisComment, &TempOggPacket)) { - _gameRef->LOG(0, "Error parsing Vorbis stream headers; corrupt stream?"); - return STATUS_FAILED; - } - m_VorbisStreams++; - if (m_VorbisStreams == 3) break; - } - - // The header pages/packets will arrive before anything else we - // care about, or the stream is not obeying spec - if (ogg_sync_pageout(&m_OggSyncState, &m_OggPage) > 0) { - if (m_TheoraStreams) - ogg_stream_pagein(&m_TheoraStreamState, &m_OggPage); - if (m_VorbisStreams) - ogg_stream_pagein(&m_VorbisStreamState, &m_OggPage); - } else { - int Ret = BufferData(&m_OggSyncState); // someone needs more data - if (Ret == 0) { - _gameRef->LOG(0, "End of file while searching for codec headers"); - return STATUS_FAILED; - } - } - } - - - - // and now we have it all. initialize decoders - if (m_TheoraStreams) { - theora_decode_init(&m_TheoraState, &m_TheoraInfo); - } else { - // tear down the partial theora setup - theora_info_clear(&m_TheoraInfo); - theora_comment_clear(&m_TheoraComment); - } - - if (m_VorbisStreams) { - vorbis_synthesis_init(&m_VorbisDSPState, &m_VorbisInfo); - vorbis_block_init(&m_VorbisDSPState, &m_VorbisBlock); - - } else { - // tear down the partial vorbis setup - vorbis_info_clear(&m_VorbisInfo); - vorbis_comment_clear(&m_VorbisComment); - } - - bool Res = STATUS_OK; - - // create sound buffer - if (m_VorbisStreams && _gameRef->m_SoundMgr->m_SoundAvailable) { - m_Sound = new CBSoundTheora(_gameRef); - _gameRef->m_SoundMgr->AddSound(m_Sound); - if (DID_FAIL(Res = m_Sound->InitializeBuffer(this))) { - _gameRef->m_SoundMgr->RemoveSound(m_Sound); - m_Sound = NULL; - _gameRef->LOG(Res, "Error initializing sound buffer for Theora file '%s'", filename); - } else { - SAFE_DELETE_ARRAY(m_AudioBuf); - m_AudioBufSize = m_Sound->m_StreamBlockSize; - m_AudioBuf = new ogg_int16_t[m_AudioBufSize]; - } - } - - // create texture - if (m_TheoraStreams && !m_Texture) { - if (_gameRef->m_UseD3D) - m_Texture = new CBSurfaceD3D(_gameRef); - else - m_Texture = new CBSurfaceDD(_gameRef); - - if (!m_Texture || DID_FAIL(Res = m_Texture->Create(m_TheoraInfo.width, m_TheoraInfo.height))) { - SAFE_DELETE(m_Texture); - } - } - - - if (!m_Subtitler) m_Subtitler = new CVidSubtitler(_gameRef); - if (m_Subtitler && _gameRef->m_VideoSubtitles) m_Subtitler->LoadSubtitles(filename, SubtitleFile); - - return Res; -#endif - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::resetStream() { - warning("VidTheoraPlayer::resetStream - stubbed"); -#if 0 - if (_sound) _sound->Stop(); - - m_TimeOffset = 0.0f; - Initialize(m_Filename); - Play(m_PlaybackType, m_PosX, m_PosY, false, false, m_Looping, 0, m_PlayZoom); -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::play(TVideoPlayback type, int x, int y, bool freezeGame, bool freezeMusic, bool looping, uint32 startTime, float forceZoom, int volume) { - if (forceZoom < 0.0f) - forceZoom = 100.0f; - if (volume < 0) - _volume = _gameRef->_soundMgr->getVolumePercent(Audio::Mixer::kSFXSoundType); - else _volume = volume; - - _freezeGame = freezeGame; - - if (!_playbackStarted && _freezeGame) - _gameRef->freeze(freezeMusic); - - _playbackStarted = false; - float width, height; - if (_theoraDecoder) { - _surface.copyFrom(*_theoraDecoder->decodeNextFrame()); - _state = THEORA_STATE_PLAYING; - _looping = looping; - _playbackType = type; - - _startTime = startTime; - _volume = volume; - _posX = x; - _posY = y; - _playZoom = forceZoom; - - width = (float)_theoraDecoder->getWidth(); - height = (float)_theoraDecoder->getHeight(); - } else { - width = (float)_gameRef->_renderer->_width; - height = (float)_gameRef->_renderer->_height; - } - - switch (type) { - case VID_PLAY_POS: - _playZoom = forceZoom; - _posX = x; - _posY = y; - break; - - case VID_PLAY_STRETCH: { - float ZoomX = (float)((float)_gameRef->_renderer->_width / width * 100); - float ZoomY = (float)((float)_gameRef->_renderer->_height / height * 100); - _playZoom = MIN(ZoomX, ZoomY); - _posX = (int)((_gameRef->_renderer->_width - width * (_playZoom / 100)) / 2); - _posY = (int)((_gameRef->_renderer->_height - height * (_playZoom / 100)) / 2); - } - break; - - case VID_PLAY_CENTER: - _playZoom = 100.0f; - _posX = (int)((_gameRef->_renderer->_width - width) / 2); - _posY = (int)((_gameRef->_renderer->_height - height) / 2); - break; - } - return STATUS_OK; -#if 0 - - m_State = THEORA_STATE_PLAYING; - - m_Looping = Looping; - m_PlaybackType = Type; - - float Width, Height; - if (m_TheoraStreams) { - Width = (float)m_TheoraInfo.width; - Height = (float)m_TheoraInfo.height; - } else { - Width = (float)_gameRef->m_Renderer->m_Width; - Height = (float)_gameRef->m_Renderer->m_Height; - } - - switch (Type) { - case VID_PLAY_POS: - m_PlayZoom = ForceZoom; - m_PosX = X; - m_PosY = Y; - break; - - case VID_PLAY_STRETCH: { - float ZoomX = (float)((float)_gameRef->m_Renderer->m_Width / Width * 100); - float ZoomY = (float)((float)_gameRef->m_Renderer->m_Height / Height * 100); - m_PlayZoom = min(ZoomX, ZoomY); - m_PosX = (_gameRef->m_Renderer->m_Width - Width * (m_PlayZoom / 100)) / 2; - m_PosY = (_gameRef->m_Renderer->m_Height - Height * (m_PlayZoom / 100)) / 2; - } - break; - - case VID_PLAY_CENTER: - m_PlayZoom = 100.0f; - m_PosX = (_gameRef->m_Renderer->m_Width - Width) / 2; - m_PosY = (_gameRef->m_Renderer->m_Height - Height) / 2; - break; - } - - - if (StartTime) SeekToTime(StartTime); - - Update(); -#endif - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::stop() { - _theoraDecoder->close(); - _state = THEORA_STATE_FINISHED; - if (_freezeGame) { - _gameRef->unfreeze(); - } -#if 0 - if (m_Sound) m_Sound->Stop(); - m_State = THEORA_STATE_FINISHED; - if (m_FreezeGame) _gameRef->Unfreeze(); -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::update() { - _currentTime = _freezeGame ? _gameRef->_liveTimer : _gameRef->_timer; - - if (!isPlaying()) return STATUS_OK; - - if (_playbackStarted /*&& m_Sound && !m_Sound->IsPlaying()*/) return STATUS_OK; - - if (_playbackStarted && !_freezeGame && _gameRef->_state == GAME_FROZEN) return STATUS_OK; - - if (_theoraDecoder) { - if (_theoraDecoder->endOfVideo() && _looping) { - warning("Should loop movie"); - _theoraDecoder->rewind(); - } else if (_theoraDecoder->endOfVideo() && !_looping) { - warning("Finished movie"); - _state = THEORA_STATE_FINISHED; - _playbackStarted = false; - if (_freezeGame) _gameRef->unfreeze(); - } - if (_state == THEORA_STATE_PLAYING) { - if (_theoraDecoder->getTimeToNextFrame() == 0) { - _surface.copyFrom(*_theoraDecoder->decodeNextFrame()); - if (_texture) { - WriteVideo(); - } - } - return STATUS_OK; - } - } - // Skip the busy-loop? - if ((!_texture || !_videoFrameReady) && !_theoraDecoder->endOfVideo()) { - // end playback - if (!_looping) { - _state = THEORA_STATE_FINISHED; - if (_freezeGame) _gameRef->unfreeze(); - return STATUS_OK; - } else { - resetStream(); - return STATUS_OK; - } - } - -#if 0 - m_CurrentTime = m_FreezeGame ? _gameRef->m_LiveTimer : _gameRef->m_Timer; - - if (!IsPlaying()) return STATUS_OK; - - if (m_PlaybackStarted && m_Sound && !m_Sound->IsPlaying()) return STATUS_OK; - - if (m_PlaybackStarted && !m_FreezeGame && _gameRef->m_State == GAME_FROZEN) return STATUS_OK; - - int Counter = 0; - while (true) { - if (m_Sound) DecodeVorbis(); - else m_AudioFrameReady = true; - - if (m_Texture) DecodeTheora(); - else m_VideoFrameReady = true; - - if ((!m_Sound || !m_AudioFrameReady) && (!m_Texture || !m_VideoFrameReady) && m_File->IsEOF()) { - // end playback - if (!m_Looping) { - m_State = THEORA_STATE_FINISHED; - if (m_Sound) m_Sound->Stop(); - if (m_FreezeGame) _gameRef->Unfreeze(); - break; - } else { - ResetStream(); - return STATUS_OK; - } - } - - - if (!m_VideoFrameReady || !m_AudioFrameReady) { - Counter++; - if (StreamInData() == 0) break; - } else break; - } - - - // If playback has begun, top audio buffer off immediately. - //if(m_Sound) WriteAudio(); - - // are we at or past time for this video frame? - if (m_PlaybackStarted && m_VideoFrameReady && (!m_FrameRendered || m_VideobufTime <= GetMovieTime())) { - //_gameRef->LOG(0, "%f %f", m_VideobufTime, GetMovieTime()); - if (m_Texture) WriteVideo(); - m_VideoFrameReady = false; - - if (m_SavedState == THEORA_STATE_PAUSED) { - Pause(); - m_SavedState = THEORA_STATE_NONE; - } - } - - // if our buffers either don't exist or are ready to go, - // we can begin playback - bool StartNow = false; - if ((!m_TheoraStreams || m_VideoFrameReady) && - (!m_VorbisStreams || m_AudioFrameReady)) StartNow = true; - // same if we've run out of input - if (m_File->IsEOF()) StartNow = true; - - - if (m_Sound) WriteAudio(); - - - if (!m_PlaybackStarted && StartNow && !m_SeekingKeyframe) { - //m_StartTime = timeGetTime(); - m_StartTime = m_CurrentTime; - if (m_Sound) { - m_Sound->SetPrivateVolume(m_Volume); - m_Sound->Play(); - } - m_PlaybackStarted = true; - } - - if (m_Subtitler && _gameRef->m_VideoSubtitles) m_Subtitler->update(GetMovieFrame()); -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -uint32 CVidTheoraPlayer::getMovieTime() { - if (!_playbackStarted) { - return 0; - } else { - return _theoraDecoder->getTime(); - } -} - - -////////////////////////////////////////////////////////////////////////// -uint32 CVidTheoraPlayer::getMovieFrame() { -#if 0 - if (!m_TheoraStreams) return 0; - float Time = GetMovieTime(); - - return Time / ((double)m_TheoraInfo.fps_denominator / m_TheoraInfo.fps_numerator); -#endif - if (_theoraDecoder) { - return _theoraDecoder->getTime(); - } else { - return 0; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::WriteVideo() { - if (!_texture) return STATUS_FAILED; - - _texture->startPixelOp(); - - writeAlpha(); - if (_alphaImage) { - _texture->putSurface(_surface, true); - } else { - _texture->putSurface(_surface, false); - } - - //RenderFrame(_texture, &yuv); - - _texture->endPixelOp(); - _videoFrameReady = true; - return STATUS_OK; -} - -void CVidTheoraPlayer::writeAlpha() { - if (_alphaImage && _surface.w == _alphaImage->getSurface()->w && _surface.h == _alphaImage->getSurface()->h) { - assert(_alphaImage->getSurface()->format.bytesPerPixel == 4); - assert(_surface.format.bytesPerPixel == 4); - const byte *alphaData = (byte *)_alphaImage->getSurface()->getBasePtr(0, 0); - int alphaPlace = (_alphaImage->getSurface()->format.aShift / 8); - alphaData += alphaPlace; - byte *imgData = (byte *)_surface.getBasePtr(0, 0); - imgData += (_surface.format.aShift / 8); - for (int i = 0; i < _surface.w * _surface.h; i++) { - *imgData = *alphaData; - alphaData += 4; - imgData += 4; - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::display(uint32 alpha) { - Rect32 rc; - bool res; - - if (_texture && _videoFrameReady) { - CBPlatform::setRect(&rc, 0, 0, _texture->getWidth(), _texture->getHeight()); - if (_playZoom == 100.0f) res = _texture->displayTrans(_posX, _posY, rc, alpha); - else res = _texture->displayTransZoom(_posX, _posY, rc, _playZoom, _playZoom, alpha); - } else res = STATUS_FAILED; -#if 0 - if (m_Subtitler && _gameRef->m_VideoSubtitles) m_Subtitler->display(); -#endif - return res; -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::setAlphaImage(const Common::String &filename) { - warning("CVidTheoraPlayer::SetAlphaImage(%s) - Not implemented", filename.c_str()); - - delete _alphaImage; - _alphaImage = new CBImage(_gameRef); - if (!_alphaImage || DID_FAIL(_alphaImage->loadFile(filename))) { - delete _alphaImage; - _alphaImage = NULL; - _alphaFilename = ""; - return STATUS_FAILED; - } - - if (_alphaFilename != filename) { - _alphaFilename = filename; - } - //TODO: Conversion. -#if 0 - SAFE_DELETE(m_AlphaImage); - m_AlphaImage = new CBImage(_gameRef); - if (!m_AlphaImage || DID_FAIL(m_AlphaImage->loadFile(filename))) { - SAFE_DELETE(m_AlphaImage); - SAFE_DELETE_ARRAY(m_AlphaFilename); - return STATUS_FAILED; - } - if (m_AlphaFilename != Filename) CBUtils::setString(&m_AlphaFilename, filename); - m_AlphaImage->Convert(IMG_TRUECOLOR); -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -byte CVidTheoraPlayer::getAlphaAt(int x, int y) { - if (_alphaImage) return _alphaImage->getAlphaAt(x, y); - else return 0xFF; -} - - -////////////////////////////////////////////////////////////////////////// -inline int intlog(int num) { - int r = 0; - while (num > 0) { - num = num / 2; - r = r + 1; - } - - return r; -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::SeekToTime(uint32 time) { - warning("CVidTheoraPlayer::SeekToTime(%d) - not supported", time); -#if 0 - if (!m_TheoraStreams) return STATUS_FAILED; - - - float TargetTime = Time / 1000.0f; - - - ogg_page page; - int read = 1; - ogg_int64_t gran; - float movieLength = 0; - DWORD LastPos = 0; - - int keyframe_granule_shift = intlog(m_TheoraInfo.keyframe_frequency_force - 1); - - while (!m_File->IsEOF() && read != 0) { - read = BufferData(&m_OggSyncState); - - while (ogg_sync_pageout(&m_OggSyncState, &page) > 0) { - int serno = ogg_page_serialno(&page); - //This is theora stream we were searching for - if (m_TheoraStreamState.serialno == serno) { - //Calculate a rough time estimate - gran = ogg_page_granulepos(&page); - if (gran >= 0) { - ogg_int64_t iframe = gran >> keyframe_granule_shift; - ogg_int64_t pframe = gran - (iframe << keyframe_granule_shift); - movieLength = (iframe + pframe) * - ((double)m_TheoraInfo.fps_denominator / m_TheoraInfo.fps_numerator); - - if (movieLength >= TargetTime) { - m_TimeOffset = movieLength; - //m_TimeOffset = TargetTime; - //m_File->Seek(LastPos); - - goto finish; - } - LastPos = m_File->GetPos(); - } - } - } - } - -finish: - ogg_sync_reset(&m_OggSyncState); - - ogg_stream_reset(&m_TheoraStreamState); - ogg_stream_reset(&m_VorbisStreamState); - - theora_clear(&m_TheoraState); - theora_decode_init(&m_TheoraState, &m_TheoraInfo); - vorbis_synthesis_restart(&m_VorbisDSPState); - - m_SeekingKeyframe = true; - - //theora_packet_iskeyframe - -#endif - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::pause() { - if (_state == THEORA_STATE_PLAYING) { - _state = THEORA_STATE_PAUSED; - _theoraDecoder->pauseVideo(true); - return STATUS_OK; - } else { - return STATUS_FAILED; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::resume() { - if (_state == THEORA_STATE_PAUSED) { - _state = THEORA_STATE_PLAYING; - _theoraDecoder->pauseVideo(false); - return STATUS_OK; - } else { - return STATUS_FAILED; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::persist(CBPersistMgr *persistMgr) { - //CBBase::persist(persistMgr); - - if (persistMgr->_saving) { - _savedPos = getMovieTime() * 1000; - _savedState = _state; - } else { - SetDefaults(); - } - - persistMgr->transfer(TMEMBER(_gameRef)); - persistMgr->transfer(TMEMBER(_savedPos)); - persistMgr->transfer(TMEMBER(_savedState)); - persistMgr->transfer(TMEMBER(_filename)); - persistMgr->transfer(TMEMBER(_alphaFilename)); - persistMgr->transfer(TMEMBER(_posX)); - persistMgr->transfer(TMEMBER(_posY)); - persistMgr->transfer(TMEMBER(_playZoom)); - persistMgr->transfer(TMEMBER_INT(_playbackType)); - persistMgr->transfer(TMEMBER(_looping)); - persistMgr->transfer(TMEMBER(_volume)); - - if (!persistMgr->_saving && (_savedState != THEORA_STATE_NONE)) { - initializeSimple(); - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool CVidTheoraPlayer::initializeSimple() { - if (DID_SUCCEED(initialize(_filename))) { - if (_alphaFilename != "") setAlphaImage(_alphaFilename); - play(_playbackType, _posX, _posY, false, false, _looping, _savedPos, _playZoom); - } else _state = THEORA_STATE_FINISHED; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -CBSurface *CVidTheoraPlayer::getTexture() { - return _texture; -} - -} // end of namespace WinterMute diff --git a/engines/wintermute/video/VidTheoraPlayer.h b/engines/wintermute/video/VidTheoraPlayer.h deleted file mode 100644 index f624c9a972..0000000000 --- a/engines/wintermute/video/VidTheoraPlayer.h +++ /dev/null @@ -1,151 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_VIDTHEORAPLAYER_H -#define WINTERMUTE_VIDTHEORAPLAYER_H - -#include "engines/wintermute/base/BBase.h" -#include "engines/wintermute/base/file/BFile.h" -#include "engines/wintermute/persistent.h" -#include "video/video_decoder.h" -#include "common/stream.h" -#include "graphics/surface.h" - -namespace WinterMute { -class CBSurface; -class CBImage; -class CVidTheoraPlayer : public CBBase { -private: - enum { - THEORA_STATE_NONE = 0, - THEORA_STATE_PLAYING = 1, - THEORA_STATE_PAUSED = 2, - THEORA_STATE_FINISHED = 3 - }; - Video::RewindableVideoDecoder *_theoraDecoder; - Graphics::Surface _surface; -public: - DECLARE_PERSISTENT(CVidTheoraPlayer, CBBase) - - CVidTheoraPlayer(CBGame *inGame); - virtual ~CVidTheoraPlayer(void); - - // external objects - Common::SeekableReadStream *_file; - Common::String _filename; - - CBSurface *_texture; - //CVidSubtitler *_subtitler; - - // control methods - bool initialize(const Common::String &filename, const Common::String &subtitleFile = NULL); - bool initializeSimple(); - bool update(); - bool play(TVideoPlayback type = VID_PLAY_CENTER, int x = 0, int y = 0, bool freezeGame = false, bool freezeMusic = true, bool Looping = false, uint32 startTime = 0, float forceZoom = -1.0f, int volume = -1); - bool stop(); - bool display(uint32 alpha = 0xFFFFFFFF); - //bool RenderFrame(CBSurface *Texture, yuv_buffer *yuv); - - bool pause(); - bool resume(); - - bool isPlaying() { - return _state == THEORA_STATE_PLAYING; - }; - bool isFinished() { - return _state == THEORA_STATE_FINISHED; - }; - bool isPaused() { - return _state == THEORA_STATE_PAUSED; - }; - - uint32 getMovieTime(); - uint32 getMovieFrame(); - - CBSurface *getTexture(); - - int _state; - uint32 _startTime; - - int _savedState; - uint32 _savedPos; - - - // alpha related - CBImage *_alphaImage; - Common::String _alphaFilename; - bool setAlphaImage(const Common::String &filename); - __inline byte getAlphaAt(int x, int y); - void writeAlpha(); - - bool SeekToTime(uint32 Time); - - - void cleanup(); - bool resetStream(); - - // video properties - TVideoPlayback _playbackType; - int _posX; - int _posY; - float _playZoom; - int _volume; - - bool _looping; - bool _dontDropFrames; - bool _freezeGame; - uint32 _currentTime; - - -private: - // seeking support - bool _seekingKeyframe; - float _timeOffset; - - bool _frameRendered; - - bool getIsFrameReady() { - return _videoFrameReady; - } -private: - bool _audioFrameReady; - bool _videoFrameReady; - float _videobufTime; - - bool WriteVideo(); - - bool _playbackStarted; - - // helpers - void SetDefaults(); - -}; - -} // end of namespace WinterMute - -#endif diff --git a/engines/wintermute/video/video_player.cpp b/engines/wintermute/video/video_player.cpp new file mode 100644 index 0000000000..49d1c6c50f --- /dev/null +++ b/engines/wintermute/video/video_player.cpp @@ -0,0 +1,470 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/video/video_player.h" + +//#pragma comment(lib, "vfw32.lib") + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////// +CVidPlayer::CVidPlayer(CBGame *inGame): CBBase(inGame) { + SetDefaults(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::SetDefaults() { + _playing = false; + + /* _aviFile = NULL; + + _audioStream = NULL; + _audioFormat = NULL; + + _videoStream = NULL; + _videoFormat = NULL; + _videoPGF = NULL;*/ + _videoEndTime = 0; + + //_sound = NULL; + _soundAvailable = false; + + //_vidRenderer = NULL; + + _startTime = 0; + _totalVideoTime = 0; + + //_lastSample = -1; + + //_targetFormat = NULL; + + _playPosX = _playPosY = 0; + _playZoom = 0.0f; + + _filename = NULL; + + _slowRendering = false; + + _currentSubtitle = 0; + _showSubtitle = false; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CVidPlayer::~CVidPlayer() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::cleanup() { +#if 0 + if (_sound) _sound->Stop(); + if (_videoPGF) AVIStreamGetFrameClose(_videoPGF); + _videoPGF = NULL; + + _playing = false; + + + if (_aviFile) AVIFileRelease(m_AviFile); + + if (_audioStream) AVIStreamRelease(m_AudioStream); + if (_videoStream) AVIStreamRelease(m_VideoStream); + + if (_audioFormat) delete [](byte *)m_AudioFormat; + if (_videoFormat) delete [](byte *)m_VideoFormat; + if (_targetFormat) delete [](byte *)m_TargetFormat; + + SAFE_DELETE(_sound); + SAFE_DELETE(_vidRenderer); + + SAFE_DELETE_ARRAY(_filename); + + for (int i = 0; i < _subtitles.getSize(); i++) delete _subtitles[i]; + _subtitles.removeAll(); + + return SetDefaults(); +#endif + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::initialize(const char *inFilename, const char *SubtitleFile) { +#if 0 + cleanup(); + + char Filename[MAX_PATH_LENGTH]; + _gameRef->_fileManager->GetFullPath(inFilename, filename); + + // open file + if (AVIFileOpen(&_aviFile, Filename, OF_READ, NULL) != 0) { + _gameRef->LOG(0, "Error opening AVI file '%s'", filename); + return STATUS_FAILED; + } + + // get video stream + if (AVIFileGetStream(_aviFile, &_videoStream, streamtypeVIDEO, 0) != 0) { + _gameRef->LOG(0, "Error finding video stream in AVI file '%s'", filename); + return STATUS_FAILED; + } + _totalVideoTime = AVIStreamEndTime(_videoStream); + + // get audio stream + if (_gameRef->m_SoundMgr->_soundAvailable && AVIFileGetStream(_aviFile, &_audioStream, streamtypeAUDIO, 0) == 0) + _soundAvailable = true; + else + _soundAvailable = false; + + + LONG Size; + + // get video format + if (AVIStreamReadFormat(m_VideoStream, 0, NULL, &Size)) { + _gameRef->LOG(0, "Error obtaining video stream format in AVI file '%s'", filename); + return STATUS_FAILED; + } + _videoFormat = (LPBITMAPINFO)new BYTE[Size]; + AVIStreamReadFormat(m_VideoStream, 0, m_VideoFormat, &Size); + + // initialize optimal target format + m_TargetFormat = (LPBITMAPV4HEADER)new BYTE[max(Size, sizeof(BITMAPV4HEADER))]; + memset(m_TargetFormat, 0, sizeof(BITMAPV4HEADER)); + memcpy(m_TargetFormat, m_VideoFormat, Size); + m_TargetFormat->bV4Size = max(Size, sizeof(BITMAPV4HEADER)); + + m_TargetFormat->bV4BitCount = 24; + m_TargetFormat->bV4V4Compression = BI_RGB; + + if (_gameRef->m_UseD3D) + m_VidRenderer = new CVidRendererD3D(_gameRef); + else + m_VidRenderer = new CVidRendererDD(_gameRef); + + if (!m_VidRenderer || DID_FAIL(m_VidRenderer->Initialize(m_VideoFormat, m_TargetFormat))) { + _gameRef->LOG(0, "Error initializing video renderer for AVI file '%s'", filename); + SAFE_DELETE(m_VidRenderer); + return STATUS_FAILED; + } + + + // create sound buffer + bool res; + + if (_soundAvailable) { + _sound = new CBSoundAVI(_gameRef); + if (DID_FAIL(res = _sound->InitializeBuffer(_audioStream))) { + SAFE_DELETE(_sound); + _soundAvailable = false; + _gameRef->LOG(res, "Error initializing sound buffer for AVI file '%s'", filename); + } + } + + if (_gameRef->_videoSubtitles) LoadSubtitles(inFilename, SubtitleFile); + + _filename = new char[strlen(filename) + 1]; + if (_filename) strcpy(_filename, filename); +#endif + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::update() { +#if 0 + if (!m_Playing) return STATUS_OK; + + bool res; + + if (_soundAvailable && m_Sound) { + res = _sound->update(); + if (DID_FAIL(res)) return res; + } + + + DWORD CurrentTime; // current playing time (in ms) + /* + if(m_SoundAvailable && m_Sound){ + CurrentTime = m_Sound->GetPosition(); // in samples + CurrentTime /= (m_Sound->m_Format.wf.nSamplesPerSec / 1000); + + if(!m_Sound->IsPlaying()) CurrentTime = m_TotalVideoTime; + } + else + CurrentTime = timeGetTime() - m_StartTime; + */ + CurrentTime = timeGetTime() - _startTime; + + if (CurrentTime >= _totalVideoTime) { + Stop(); + return STATUS_OK; + } + + + // get and render frame + DWORD sample = AVIStreamTimeToSample(_videoStream, CurrentTime); + if (sample != _lastSample) { + _lastSample = sample; + + // process subtitles + _showSubtitle = false; + while (_currentSubtitle < _subtitles.getSize()) { + int End = _subtitles[_currentSubtitle]->m_EndFrame; + + bool NextFrameOK = (_currentSubtitle < _subtitles.getSize() - 1 && _subtitles[_currentSubtitle + 1]->_startFrame <= sample); + + if (sample > End) { + if (NextFrameOK) { + _currentSubtitle++; + } else { + _showSubtitle = (End == 0); + break; + } + } else { + _showSubtitle = true; + break; + } + } + + + // render frame + LPBITMAPINFOHEADER FrameData = (LPBITMAPINFOHEADER)AVIStreamGetFrame(m_VideoPGF, sample); + if (FrameData) { + if (_slowRendering) return _vidRenderer->ProcessFrameSlow(FrameData); + else return _vidRenderer->ProcessFrame(FrameData); + } else return STATUS_FAILED; + } else return STATUS_OK; +#endif + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::display() { +#if 0 + if (!m_Playing) return STATUS_OK; + + bool res; + if (_vidRenderer) res = _vidRenderer->display(m_PlayPosX, m_PlayPosY, m_PlayZoom); + else res = STATUS_FAILED; + + // display subtitle + if (m_ShowSubtitle) { + CBFont *font = _gameRef->_videoFont ? _gameRef->_videoFont : _gameRef->_systemFont; + int Height = font->GetTextHeight((BYTE *)m_Subtitles[_currentSubtitle]->_text, _gameRef->_renderer->_width); + font->drawText((byte *)_subtitles[m_CurrentSubtitle]->_text, 0, _gameRef->_renderer->_height - Height - 5, _gameRef->_renderer->_width, TAL_CENTER); + } + + return res; +#endif + return 0; +} + + + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::play(TVideoPlayback Type, int X, int Y, bool FreezeMusic) { +#if 0 + if (!_videoStream || !_vidRenderer) return STATUS_FAILED; + + switch (Type) { + case VID_PLAY_POS: + _playZoom = 100.0f; + _playPosX = X; + _playPosY = Y; + break; + + case VID_PLAY_STRETCH: { + float ZoomX = (float)((float)_gameRef->_renderer->m_Width / (float)_videoFormat->bmiHeader.biWidth * 100); + float ZoomY = (float)((float)_gameRef->_renderer->m_Height / (float)_videoFormat->bmiHeader.biHeight * 100); + _playZoom = min(ZoomX, ZoomY); + _playPosX = (_gameRef->_renderer->_width - _videoFormat->bmiHeader.biWidth * (_playZoom / 100)) / 2; + _playPosY = (_gameRef->_renderer->_height - _videoFormat->bmiHeader.biHeight * (_playZoom / 100)) / 2; + } + break; + + case VID_PLAY_CENTER: + _playZoom = 100.0f; + _playPosX = (_gameRef->_renderer->_width - _videoFormat->bmiHeader.biWidth) / 2; + _playPosY = (_gameRef->_renderer->_height - _videoFormat->bmiHeader.biHeight) / 2; + break; + } + + _targetFormat->bV4BitCount = 24; + _targetFormat->bV4V4Compression = BI_RGB; + + + _videoPGF = AVIStreamGetFrameOpen(_videoStream, (LPBITMAPINFOHEADER)m_TargetFormat); + if (!_videoPGF) { + _videoPGF = AVIStreamGetFrameOpen(_videoStream, NULL); + if (!_videoPGF) { + _gameRef->LOG(0, "Error: Unsupported AVI format (file '%s')", m_Filename); + cleanup(); + return STATUS_FAILED; + } else { + _gameRef->LOG(0, "Performance warning: non-optimal AVI format, using generic (i.e. slow) rendering routines (file '%s')", m_Filename); + _slowRendering = true; + } + } else _slowRendering = false; + + // HACK!!! + _slowRendering = true; + + + _currentSubtitle = 0; + + _gameRef->Freeze(FreezeMusic); + + _playing = true; + if (_sound) _sound->Play(); + _startTime = timeGetTime(); +#endif + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::stop() { +#if 0 + if (!_playing) return STATUS_OK; + + cleanup(); + + _gameRef->Unfreeze(); +#endif + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::isPlaying() { + return _playing; +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidPlayer::loadSubtitles(const char *filename, const char *SubtitleFile) { +#if 0 + if (!Filename) return STATUS_OK; + + char NewFile[MAX_PATH_LENGTH]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char fname[_MAX_FNAME]; + + if (SubtitleFile) { + strcpy(NewFile, SubtitleFile); + } else { + _splitpath(filename, drive, dir, fname, NULL); + _makepath(NewFile, drive, dir, fname, ".SUB"); + } + + DWORD Size; + BYTE *Buffer = _gameRef->m_FileManager->readWholeFile(NewFile, &Size, false); + if (Buffer == NULL) return STATUS_OK; // no subtitles + + + LONG Start, End; + bool InToken; + char *TokenStart; + int TokenLength; + int TokenPos; + int TextLength; + + int Pos = 0; + int LineLength = 0; + while (Pos < Size) { + Start = End = -1; + InToken = false; + TokenPos = -1; + TextLength = 0; + + LineLength = 0; + while (Pos + LineLength < Size && Buffer[Pos + LineLength] != '\n' && Buffer[Pos + LineLength] != '\0') LineLength++; + + int RealLength = LineLength - (Pos + LineLength >= Size ? 0 : 1); + char *Text = new char[RealLength + 1]; + char *line = (char *)&Buffer[Pos]; + + for (int i = 0; i < RealLength; i++) { + if (line[i] == '{') { + if (!InToken) { + InToken = true; + TokenStart = line + i + 1; + TokenLength = 0; + TokenPos++; + } else TokenLength++; + } else if (line[i] == '}') { + if (InToken) { + InToken = false; + char *Token = new char[TokenLength + 1]; + strncpy(Token, TokenStart, TokenLength); + Token[TokenLength] = '\0'; + if (TokenPos == 0) Start = atoi(Token); + else if (TokenPos == 1) End = atoi(Token); + + delete [] Token; + } else { + Text[TextLength] = line[i]; + TextLength++; + } + } else { + if (InToken) { + TokenLength++; + } else { + Text[TextLength] = line[i]; + if (Text[TextLength] == '|') Text[TextLength] = '\n'; + TextLength++; + } + } + } + Text[TextLength] = '\0'; + + if (Start != -1 && TextLength > 0) _subtitles.add(new CVidSubtitle(_gameRef, Text, Start, End)); + + delete [] Text; + + Pos += LineLength + 1; + } + + delete [] Buffer; +#endif + return STATUS_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/video/video_player.h b/engines/wintermute/video/video_player.h new file mode 100644 index 0000000000..ca6c7fdec5 --- /dev/null +++ b/engines/wintermute/video/video_player.h @@ -0,0 +1,93 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_VIDPLAYER_H +#define WINTERMUTE_VIDPLAYER_H + +#include "engines/wintermute/dctypes.h" // Added by ClassView +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "engines/wintermute/base/base.h" + +#define MAX_AUDIO_STREAMS 5 +#define MAX_VIDEO_STREAMS 5 + + +namespace WinterMute { + +class CVidPlayer : public CBBase { +public: + bool _showSubtitle; + int _currentSubtitle; + bool loadSubtitles(const char *filename, const char *SubtitleFile); + bool _slowRendering; + bool isPlaying(); + char *_filename; + bool stop(); + bool play(TVideoPlayback Type = VID_PLAY_CENTER, int X = 0, int Y = 0, bool FreezeMusic = true); + uint32 _totalVideoTime; + uint32 _startTime; + //CVidRenderer *_vidRenderer; + //CBSoundAVI *_sound; + bool _soundAvailable; + bool SetDefaults(); + bool _playing; + bool display(); + bool update(); + bool initialize(const char *inFilename, const char *SubtitleFile = NULL); + bool cleanup(); + CVidPlayer(CBGame *inGame); + virtual ~CVidPlayer(); + + /*PAVIFILE _aviFile; + + LONG _lastSample; + + PAVISTREAM _audioStream; + PAVISTREAM _videoStream; + + LPWAVEFORMAT _audioFormat; + + LPBITMAPINFO _videoFormat; + PGETFRAME _videoPGF;*/ + uint32 _videoEndTime; + + int _playPosX; + int _playPosY; + float _playZoom; + + /* LPBITMAPV4HEADER _targetFormat; + + CBArray _subtitles;*/ +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp new file mode 100644 index 0000000000..e3c120ff86 --- /dev/null +++ b/engines/wintermute/video/video_theora_player.cpp @@ -0,0 +1,850 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 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/video/video_theora_player.h" +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" +#include "engines/wintermute/base/gfx/base_image.h" +#include "engines/wintermute/base/sound/base_sound_manager.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/video/decoders/theora_decoder.h" +#include "common/system.h" +//#pragma comment(lib, "libtheora.lib") + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CVidTheoraPlayer, false) + +////////////////////////////////////////////////////////////////////////// +CVidTheoraPlayer::CVidTheoraPlayer(CBGame *inGame): CBBase(inGame) { + SetDefaults(); +} + +////////////////////////////////////////////////////////////////////////// +void CVidTheoraPlayer::SetDefaults() { + + _file = NULL; + _filename = ""; + _startTime = 0; + _looping = false; + + _freezeGame = false; + _currentTime = 0; + + _state = THEORA_STATE_NONE; + + _videoFrameReady = false; + _audioFrameReady = false; + _videobufTime = 0; + + _playbackStarted = false; + _dontDropFrames = false; + + _texture = NULL; + _alphaImage = NULL; + _alphaFilename = ""; + + _frameRendered = false; + + _seekingKeyframe = false; + _timeOffset = 0.0f; + + _posX = _posY = 0; + _playbackType = VID_PLAY_CENTER; + _playZoom = 0.0f; + + _savedState = THEORA_STATE_NONE; + _savedPos = 0; + _volume = 100; + _theoraDecoder = NULL; +#if 0 + _vorbisStreams = _theoraStreams = 0; + + GenLookupTables(); + + _subtitler = NULL; +#endif +} + +////////////////////////////////////////////////////////////////////////// +CVidTheoraPlayer::~CVidTheoraPlayer(void) { + cleanup(); + + /* SAFE_DELETE_ARRAY(_filename); + SAFE_DELETE_ARRAY(_alphaFilename); + SAFE_DELETE(_texture); + SAFE_DELETE(_alphaImage);*/ +// SAFE_DELETE(_subtitler); +} + +////////////////////////////////////////////////////////////////////////// +void CVidTheoraPlayer::cleanup() { + if (_file) { + _gameRef->_fileManager->closeFile(_file); + _file = NULL; + } + + _surface.free(); + delete _theoraDecoder; + _theoraDecoder = NULL; + delete _alphaImage; + _alphaImage = NULL; + delete _texture; + _texture = NULL; +#if 0 + if (m_Sound) { + _gameRef->m_SoundMgr->RemoveSound(m_Sound); + m_Sound = NULL; + } + + SAFE_DELETE_ARRAY(m_AudioBuf); + m_AudioBufFill = 0; + m_AudioBufSize = 0; +#endif +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::initialize(const Common::String &filename, const Common::String &subtitleFile) { + cleanup(); + + _filename = filename; + _file = _gameRef->_fileManager->openFile(filename, true, false); + if (!_file) return STATUS_FAILED; + + //if (Filename != _filename) CBUtils::setString(&_filename, filename); +#if defined (USE_THEORADEC) + _theoraDecoder = new TheoraDecoder(); +#else + return STATUS_FAILED; +#endif + _theoraDecoder->loadStream(_file); + + if (!_theoraDecoder->isVideoLoaded()) + return STATUS_FAILED; + + _state = THEORA_STATE_PAUSED; + + // Additional setup. + _surface.create(_theoraDecoder->getWidth(), _theoraDecoder->getHeight(), _theoraDecoder->getPixelFormat()); + _texture = new CBSurfaceOSystem(_gameRef); + _texture->create(_theoraDecoder->getWidth(), _theoraDecoder->getHeight()); + _state = THEORA_STATE_PLAYING; + _playZoom = 100; + + return STATUS_OK; +#if 0 + cleanup(); + + _file = _gameRef->_fileManager->openFile(filename); + if (!_file) return STATUS_FAILED; + + if (Filename != _filename) CBUtils::setString(&_filename, filename); + + // start up Ogg stream synchronization layer + ogg_sync_init(&m_OggSyncState); + + // init supporting Vorbis structures needed in header parsing + vorbis_comment_init(&m_VorbisComment); + vorbis_info_init(&m_VorbisInfo); + + // init supporting Theora structures needed in header parsing + theora_comment_init(&m_TheoraComment); + theora_info_init(&m_TheoraInfo); + + + + // Ogg file open; parse the headers + // Only interested in Vorbis/Theora streams + ogg_packet TempOggPacket; + bool IsDone = false; + while (!IsDone) { + int BytesRead = BufferData(&m_OggSyncState); + if (BytesRead == 0) break; + + while (ogg_sync_pageout(&m_OggSyncState, &m_OggPage) > 0) { + ogg_stream_state OggStateTest; + + // is this a mandated initial header? If not, stop parsing + if (!ogg_page_bos(&m_OggPage)) { + // don't leak the page; get it into the appropriate stream + if (m_TheoraStreams) + ogg_stream_pagein(&m_TheoraStreamState, &m_OggPage); + if (m_VorbisStreams) + ogg_stream_pagein(&m_VorbisStreamState, &m_OggPage); + + IsDone = true; + break; + } + + ogg_stream_init(&OggStateTest, ogg_page_serialno(&m_OggPage)); + ogg_stream_pagein(&OggStateTest, &m_OggPage); + ogg_stream_packetout(&OggStateTest, &TempOggPacket); + + // identify the codec: try theora + if (!m_TheoraStreams && theora_decode_header(&m_TheoraInfo, &m_TheoraComment, &TempOggPacket) >= 0) { + // it is theora + memcpy(&m_TheoraStreamState, &OggStateTest, sizeof(OggStateTest)); + m_TheoraStreams = 1; + } else if (!m_VorbisStreams && vorbis_synthesis_headerin(&m_VorbisInfo, &m_VorbisComment, &TempOggPacket) >= 0) { + // it is vorbis + memcpy(&m_VorbisStreamState, &OggStateTest, sizeof(OggStateTest)); + m_VorbisStreams = 1; + } else { + // whatever it is, we don't care about it + ogg_stream_clear(&OggStateTest); + } + } + } + + // we're expecting more header packets + while ((m_TheoraStreams && m_TheoraStreams < 3) || (m_VorbisStreams && m_VorbisStreams < 3)) { + int Ret; + + // look for further theora headers + while (m_TheoraStreams && (m_TheoraStreams < 3) && (Ret = ogg_stream_packetout(&m_TheoraStreamState, &TempOggPacket))) { + if (Ret < 0) { + _gameRef->LOG(0, "Error parsing Theora stream headers; corrupt stream?"); + return STATUS_FAILED; + } + if (theora_decode_header(&m_TheoraInfo, &m_TheoraComment, &TempOggPacket)) { + _gameRef->LOG(0, "Error parsing Theora stream headers; corrupt stream?"); + return STATUS_FAILED; + } + m_TheoraStreams++; + if (m_TheoraStreams == 3) break; + } + + /* look for more vorbis header packets */ + while (m_VorbisStreams && (m_VorbisStreams < 3) && (Ret = ogg_stream_packetout(&m_VorbisStreamState, &TempOggPacket))) { + if (Ret < 0) { + _gameRef->LOG(0, "Error parsing Vorbis stream headers; corrupt stream?"); + return STATUS_FAILED; + } + if (vorbis_synthesis_headerin(&m_VorbisInfo, &m_VorbisComment, &TempOggPacket)) { + _gameRef->LOG(0, "Error parsing Vorbis stream headers; corrupt stream?"); + return STATUS_FAILED; + } + m_VorbisStreams++; + if (m_VorbisStreams == 3) break; + } + + // The header pages/packets will arrive before anything else we + // care about, or the stream is not obeying spec + if (ogg_sync_pageout(&m_OggSyncState, &m_OggPage) > 0) { + if (m_TheoraStreams) + ogg_stream_pagein(&m_TheoraStreamState, &m_OggPage); + if (m_VorbisStreams) + ogg_stream_pagein(&m_VorbisStreamState, &m_OggPage); + } else { + int Ret = BufferData(&m_OggSyncState); // someone needs more data + if (Ret == 0) { + _gameRef->LOG(0, "End of file while searching for codec headers"); + return STATUS_FAILED; + } + } + } + + + + // and now we have it all. initialize decoders + if (m_TheoraStreams) { + theora_decode_init(&m_TheoraState, &m_TheoraInfo); + } else { + // tear down the partial theora setup + theora_info_clear(&m_TheoraInfo); + theora_comment_clear(&m_TheoraComment); + } + + if (m_VorbisStreams) { + vorbis_synthesis_init(&m_VorbisDSPState, &m_VorbisInfo); + vorbis_block_init(&m_VorbisDSPState, &m_VorbisBlock); + + } else { + // tear down the partial vorbis setup + vorbis_info_clear(&m_VorbisInfo); + vorbis_comment_clear(&m_VorbisComment); + } + + bool Res = STATUS_OK; + + // create sound buffer + if (m_VorbisStreams && _gameRef->m_SoundMgr->m_SoundAvailable) { + m_Sound = new CBSoundTheora(_gameRef); + _gameRef->m_SoundMgr->AddSound(m_Sound); + if (DID_FAIL(Res = m_Sound->InitializeBuffer(this))) { + _gameRef->m_SoundMgr->RemoveSound(m_Sound); + m_Sound = NULL; + _gameRef->LOG(Res, "Error initializing sound buffer for Theora file '%s'", filename); + } else { + SAFE_DELETE_ARRAY(m_AudioBuf); + m_AudioBufSize = m_Sound->m_StreamBlockSize; + m_AudioBuf = new ogg_int16_t[m_AudioBufSize]; + } + } + + // create texture + if (m_TheoraStreams && !m_Texture) { + if (_gameRef->m_UseD3D) + m_Texture = new CBSurfaceD3D(_gameRef); + else + m_Texture = new CBSurfaceDD(_gameRef); + + if (!m_Texture || DID_FAIL(Res = m_Texture->Create(m_TheoraInfo.width, m_TheoraInfo.height))) { + SAFE_DELETE(m_Texture); + } + } + + + if (!m_Subtitler) m_Subtitler = new CVidSubtitler(_gameRef); + if (m_Subtitler && _gameRef->m_VideoSubtitles) m_Subtitler->LoadSubtitles(filename, SubtitleFile); + + return Res; +#endif + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::resetStream() { + warning("VidTheoraPlayer::resetStream - stubbed"); +#if 0 + if (_sound) _sound->Stop(); + + m_TimeOffset = 0.0f; + Initialize(m_Filename); + Play(m_PlaybackType, m_PosX, m_PosY, false, false, m_Looping, 0, m_PlayZoom); +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::play(TVideoPlayback type, int x, int y, bool freezeGame, bool freezeMusic, bool looping, uint32 startTime, float forceZoom, int volume) { + if (forceZoom < 0.0f) + forceZoom = 100.0f; + if (volume < 0) + _volume = _gameRef->_soundMgr->getVolumePercent(Audio::Mixer::kSFXSoundType); + else _volume = volume; + + _freezeGame = freezeGame; + + if (!_playbackStarted && _freezeGame) + _gameRef->freeze(freezeMusic); + + _playbackStarted = false; + float width, height; + if (_theoraDecoder) { + _surface.copyFrom(*_theoraDecoder->decodeNextFrame()); + _state = THEORA_STATE_PLAYING; + _looping = looping; + _playbackType = type; + + _startTime = startTime; + _volume = volume; + _posX = x; + _posY = y; + _playZoom = forceZoom; + + width = (float)_theoraDecoder->getWidth(); + height = (float)_theoraDecoder->getHeight(); + } else { + width = (float)_gameRef->_renderer->_width; + height = (float)_gameRef->_renderer->_height; + } + + switch (type) { + case VID_PLAY_POS: + _playZoom = forceZoom; + _posX = x; + _posY = y; + break; + + case VID_PLAY_STRETCH: { + float ZoomX = (float)((float)_gameRef->_renderer->_width / width * 100); + float ZoomY = (float)((float)_gameRef->_renderer->_height / height * 100); + _playZoom = MIN(ZoomX, ZoomY); + _posX = (int)((_gameRef->_renderer->_width - width * (_playZoom / 100)) / 2); + _posY = (int)((_gameRef->_renderer->_height - height * (_playZoom / 100)) / 2); + } + break; + + case VID_PLAY_CENTER: + _playZoom = 100.0f; + _posX = (int)((_gameRef->_renderer->_width - width) / 2); + _posY = (int)((_gameRef->_renderer->_height - height) / 2); + break; + } + return STATUS_OK; +#if 0 + + m_State = THEORA_STATE_PLAYING; + + m_Looping = Looping; + m_PlaybackType = Type; + + float Width, Height; + if (m_TheoraStreams) { + Width = (float)m_TheoraInfo.width; + Height = (float)m_TheoraInfo.height; + } else { + Width = (float)_gameRef->m_Renderer->m_Width; + Height = (float)_gameRef->m_Renderer->m_Height; + } + + switch (Type) { + case VID_PLAY_POS: + m_PlayZoom = ForceZoom; + m_PosX = X; + m_PosY = Y; + break; + + case VID_PLAY_STRETCH: { + float ZoomX = (float)((float)_gameRef->m_Renderer->m_Width / Width * 100); + float ZoomY = (float)((float)_gameRef->m_Renderer->m_Height / Height * 100); + m_PlayZoom = min(ZoomX, ZoomY); + m_PosX = (_gameRef->m_Renderer->m_Width - Width * (m_PlayZoom / 100)) / 2; + m_PosY = (_gameRef->m_Renderer->m_Height - Height * (m_PlayZoom / 100)) / 2; + } + break; + + case VID_PLAY_CENTER: + m_PlayZoom = 100.0f; + m_PosX = (_gameRef->m_Renderer->m_Width - Width) / 2; + m_PosY = (_gameRef->m_Renderer->m_Height - Height) / 2; + break; + } + + + if (StartTime) SeekToTime(StartTime); + + Update(); +#endif + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::stop() { + _theoraDecoder->close(); + _state = THEORA_STATE_FINISHED; + if (_freezeGame) { + _gameRef->unfreeze(); + } +#if 0 + if (m_Sound) m_Sound->Stop(); + m_State = THEORA_STATE_FINISHED; + if (m_FreezeGame) _gameRef->Unfreeze(); +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::update() { + _currentTime = _freezeGame ? _gameRef->_liveTimer : _gameRef->_timer; + + if (!isPlaying()) return STATUS_OK; + + if (_playbackStarted /*&& m_Sound && !m_Sound->IsPlaying()*/) return STATUS_OK; + + if (_playbackStarted && !_freezeGame && _gameRef->_state == GAME_FROZEN) return STATUS_OK; + + if (_theoraDecoder) { + if (_theoraDecoder->endOfVideo() && _looping) { + warning("Should loop movie"); + _theoraDecoder->rewind(); + } else if (_theoraDecoder->endOfVideo() && !_looping) { + warning("Finished movie"); + _state = THEORA_STATE_FINISHED; + _playbackStarted = false; + if (_freezeGame) _gameRef->unfreeze(); + } + if (_state == THEORA_STATE_PLAYING) { + if (_theoraDecoder->getTimeToNextFrame() == 0) { + _surface.copyFrom(*_theoraDecoder->decodeNextFrame()); + if (_texture) { + WriteVideo(); + } + } + return STATUS_OK; + } + } + // Skip the busy-loop? + if ((!_texture || !_videoFrameReady) && !_theoraDecoder->endOfVideo()) { + // end playback + if (!_looping) { + _state = THEORA_STATE_FINISHED; + if (_freezeGame) _gameRef->unfreeze(); + return STATUS_OK; + } else { + resetStream(); + return STATUS_OK; + } + } + +#if 0 + m_CurrentTime = m_FreezeGame ? _gameRef->m_LiveTimer : _gameRef->m_Timer; + + if (!IsPlaying()) return STATUS_OK; + + if (m_PlaybackStarted && m_Sound && !m_Sound->IsPlaying()) return STATUS_OK; + + if (m_PlaybackStarted && !m_FreezeGame && _gameRef->m_State == GAME_FROZEN) return STATUS_OK; + + int Counter = 0; + while (true) { + if (m_Sound) DecodeVorbis(); + else m_AudioFrameReady = true; + + if (m_Texture) DecodeTheora(); + else m_VideoFrameReady = true; + + if ((!m_Sound || !m_AudioFrameReady) && (!m_Texture || !m_VideoFrameReady) && m_File->IsEOF()) { + // end playback + if (!m_Looping) { + m_State = THEORA_STATE_FINISHED; + if (m_Sound) m_Sound->Stop(); + if (m_FreezeGame) _gameRef->Unfreeze(); + break; + } else { + ResetStream(); + return STATUS_OK; + } + } + + + if (!m_VideoFrameReady || !m_AudioFrameReady) { + Counter++; + if (StreamInData() == 0) break; + } else break; + } + + + // If playback has begun, top audio buffer off immediately. + //if(m_Sound) WriteAudio(); + + // are we at or past time for this video frame? + if (m_PlaybackStarted && m_VideoFrameReady && (!m_FrameRendered || m_VideobufTime <= GetMovieTime())) { + //_gameRef->LOG(0, "%f %f", m_VideobufTime, GetMovieTime()); + if (m_Texture) WriteVideo(); + m_VideoFrameReady = false; + + if (m_SavedState == THEORA_STATE_PAUSED) { + Pause(); + m_SavedState = THEORA_STATE_NONE; + } + } + + // if our buffers either don't exist or are ready to go, + // we can begin playback + bool StartNow = false; + if ((!m_TheoraStreams || m_VideoFrameReady) && + (!m_VorbisStreams || m_AudioFrameReady)) StartNow = true; + // same if we've run out of input + if (m_File->IsEOF()) StartNow = true; + + + if (m_Sound) WriteAudio(); + + + if (!m_PlaybackStarted && StartNow && !m_SeekingKeyframe) { + //m_StartTime = timeGetTime(); + m_StartTime = m_CurrentTime; + if (m_Sound) { + m_Sound->SetPrivateVolume(m_Volume); + m_Sound->Play(); + } + m_PlaybackStarted = true; + } + + if (m_Subtitler && _gameRef->m_VideoSubtitles) m_Subtitler->update(GetMovieFrame()); +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +uint32 CVidTheoraPlayer::getMovieTime() { + if (!_playbackStarted) { + return 0; + } else { + return _theoraDecoder->getTime(); + } +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CVidTheoraPlayer::getMovieFrame() { +#if 0 + if (!m_TheoraStreams) return 0; + float Time = GetMovieTime(); + + return Time / ((double)m_TheoraInfo.fps_denominator / m_TheoraInfo.fps_numerator); +#endif + if (_theoraDecoder) { + return _theoraDecoder->getTime(); + } else { + return 0; + } +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::WriteVideo() { + if (!_texture) return STATUS_FAILED; + + _texture->startPixelOp(); + + writeAlpha(); + if (_alphaImage) { + _texture->putSurface(_surface, true); + } else { + _texture->putSurface(_surface, false); + } + + //RenderFrame(_texture, &yuv); + + _texture->endPixelOp(); + _videoFrameReady = true; + return STATUS_OK; +} + +void CVidTheoraPlayer::writeAlpha() { + if (_alphaImage && _surface.w == _alphaImage->getSurface()->w && _surface.h == _alphaImage->getSurface()->h) { + assert(_alphaImage->getSurface()->format.bytesPerPixel == 4); + assert(_surface.format.bytesPerPixel == 4); + const byte *alphaData = (byte *)_alphaImage->getSurface()->getBasePtr(0, 0); + int alphaPlace = (_alphaImage->getSurface()->format.aShift / 8); + alphaData += alphaPlace; + byte *imgData = (byte *)_surface.getBasePtr(0, 0); + imgData += (_surface.format.aShift / 8); + for (int i = 0; i < _surface.w * _surface.h; i++) { + *imgData = *alphaData; + alphaData += 4; + imgData += 4; + } + } +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::display(uint32 alpha) { + Rect32 rc; + bool res; + + if (_texture && _videoFrameReady) { + CBPlatform::setRect(&rc, 0, 0, _texture->getWidth(), _texture->getHeight()); + if (_playZoom == 100.0f) res = _texture->displayTrans(_posX, _posY, rc, alpha); + else res = _texture->displayTransZoom(_posX, _posY, rc, _playZoom, _playZoom, alpha); + } else res = STATUS_FAILED; +#if 0 + if (m_Subtitler && _gameRef->m_VideoSubtitles) m_Subtitler->display(); +#endif + return res; +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::setAlphaImage(const Common::String &filename) { + warning("CVidTheoraPlayer::SetAlphaImage(%s) - Not implemented", filename.c_str()); + + delete _alphaImage; + _alphaImage = new CBImage(_gameRef); + if (!_alphaImage || DID_FAIL(_alphaImage->loadFile(filename))) { + delete _alphaImage; + _alphaImage = NULL; + _alphaFilename = ""; + return STATUS_FAILED; + } + + if (_alphaFilename != filename) { + _alphaFilename = filename; + } + //TODO: Conversion. +#if 0 + SAFE_DELETE(m_AlphaImage); + m_AlphaImage = new CBImage(_gameRef); + if (!m_AlphaImage || DID_FAIL(m_AlphaImage->loadFile(filename))) { + SAFE_DELETE(m_AlphaImage); + SAFE_DELETE_ARRAY(m_AlphaFilename); + return STATUS_FAILED; + } + if (m_AlphaFilename != Filename) CBUtils::setString(&m_AlphaFilename, filename); + m_AlphaImage->Convert(IMG_TRUECOLOR); +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +byte CVidTheoraPlayer::getAlphaAt(int x, int y) { + if (_alphaImage) return _alphaImage->getAlphaAt(x, y); + else return 0xFF; +} + + +////////////////////////////////////////////////////////////////////////// +inline int intlog(int num) { + int r = 0; + while (num > 0) { + num = num / 2; + r = r + 1; + } + + return r; +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::SeekToTime(uint32 time) { + warning("CVidTheoraPlayer::SeekToTime(%d) - not supported", time); +#if 0 + if (!m_TheoraStreams) return STATUS_FAILED; + + + float TargetTime = Time / 1000.0f; + + + ogg_page page; + int read = 1; + ogg_int64_t gran; + float movieLength = 0; + DWORD LastPos = 0; + + int keyframe_granule_shift = intlog(m_TheoraInfo.keyframe_frequency_force - 1); + + while (!m_File->IsEOF() && read != 0) { + read = BufferData(&m_OggSyncState); + + while (ogg_sync_pageout(&m_OggSyncState, &page) > 0) { + int serno = ogg_page_serialno(&page); + //This is theora stream we were searching for + if (m_TheoraStreamState.serialno == serno) { + //Calculate a rough time estimate + gran = ogg_page_granulepos(&page); + if (gran >= 0) { + ogg_int64_t iframe = gran >> keyframe_granule_shift; + ogg_int64_t pframe = gran - (iframe << keyframe_granule_shift); + movieLength = (iframe + pframe) * + ((double)m_TheoraInfo.fps_denominator / m_TheoraInfo.fps_numerator); + + if (movieLength >= TargetTime) { + m_TimeOffset = movieLength; + //m_TimeOffset = TargetTime; + //m_File->Seek(LastPos); + + goto finish; + } + LastPos = m_File->GetPos(); + } + } + } + } + +finish: + ogg_sync_reset(&m_OggSyncState); + + ogg_stream_reset(&m_TheoraStreamState); + ogg_stream_reset(&m_VorbisStreamState); + + theora_clear(&m_TheoraState); + theora_decode_init(&m_TheoraState, &m_TheoraInfo); + vorbis_synthesis_restart(&m_VorbisDSPState); + + m_SeekingKeyframe = true; + + //theora_packet_iskeyframe + +#endif + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::pause() { + if (_state == THEORA_STATE_PLAYING) { + _state = THEORA_STATE_PAUSED; + _theoraDecoder->pauseVideo(true); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::resume() { + if (_state == THEORA_STATE_PAUSED) { + _state = THEORA_STATE_PLAYING; + _theoraDecoder->pauseVideo(false); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::persist(CBPersistMgr *persistMgr) { + //CBBase::persist(persistMgr); + + if (persistMgr->_saving) { + _savedPos = getMovieTime() * 1000; + _savedState = _state; + } else { + SetDefaults(); + } + + persistMgr->transfer(TMEMBER(_gameRef)); + persistMgr->transfer(TMEMBER(_savedPos)); + persistMgr->transfer(TMEMBER(_savedState)); + persistMgr->transfer(TMEMBER(_filename)); + persistMgr->transfer(TMEMBER(_alphaFilename)); + persistMgr->transfer(TMEMBER(_posX)); + persistMgr->transfer(TMEMBER(_posY)); + persistMgr->transfer(TMEMBER(_playZoom)); + persistMgr->transfer(TMEMBER_INT(_playbackType)); + persistMgr->transfer(TMEMBER(_looping)); + persistMgr->transfer(TMEMBER(_volume)); + + if (!persistMgr->_saving && (_savedState != THEORA_STATE_NONE)) { + initializeSimple(); + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CVidTheoraPlayer::initializeSimple() { + if (DID_SUCCEED(initialize(_filename))) { + if (_alphaFilename != "") setAlphaImage(_alphaFilename); + play(_playbackType, _posX, _posY, false, false, _looping, _savedPos, _playZoom); + } else _state = THEORA_STATE_FINISHED; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +CBSurface *CVidTheoraPlayer::getTexture() { + return _texture; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/video/video_theora_player.h b/engines/wintermute/video/video_theora_player.h new file mode 100644 index 0000000000..5bf8e165c7 --- /dev/null +++ b/engines/wintermute/video/video_theora_player.h @@ -0,0 +1,151 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_VIDTHEORAPLAYER_H +#define WINTERMUTE_VIDTHEORAPLAYER_H + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/base/file/base_file.h" +#include "engines/wintermute/persistent.h" +#include "video/video_decoder.h" +#include "common/stream.h" +#include "graphics/surface.h" + +namespace WinterMute { +class CBSurface; +class CBImage; +class CVidTheoraPlayer : public CBBase { +private: + enum { + THEORA_STATE_NONE = 0, + THEORA_STATE_PLAYING = 1, + THEORA_STATE_PAUSED = 2, + THEORA_STATE_FINISHED = 3 + }; + Video::RewindableVideoDecoder *_theoraDecoder; + Graphics::Surface _surface; +public: + DECLARE_PERSISTENT(CVidTheoraPlayer, CBBase) + + CVidTheoraPlayer(CBGame *inGame); + virtual ~CVidTheoraPlayer(void); + + // external objects + Common::SeekableReadStream *_file; + Common::String _filename; + + CBSurface *_texture; + //CVidSubtitler *_subtitler; + + // control methods + bool initialize(const Common::String &filename, const Common::String &subtitleFile = NULL); + bool initializeSimple(); + bool update(); + bool play(TVideoPlayback type = VID_PLAY_CENTER, int x = 0, int y = 0, bool freezeGame = false, bool freezeMusic = true, bool Looping = false, uint32 startTime = 0, float forceZoom = -1.0f, int volume = -1); + bool stop(); + bool display(uint32 alpha = 0xFFFFFFFF); + //bool RenderFrame(CBSurface *Texture, yuv_buffer *yuv); + + bool pause(); + bool resume(); + + bool isPlaying() { + return _state == THEORA_STATE_PLAYING; + }; + bool isFinished() { + return _state == THEORA_STATE_FINISHED; + }; + bool isPaused() { + return _state == THEORA_STATE_PAUSED; + }; + + uint32 getMovieTime(); + uint32 getMovieFrame(); + + CBSurface *getTexture(); + + int _state; + uint32 _startTime; + + int _savedState; + uint32 _savedPos; + + + // alpha related + CBImage *_alphaImage; + Common::String _alphaFilename; + bool setAlphaImage(const Common::String &filename); + __inline byte getAlphaAt(int x, int y); + void writeAlpha(); + + bool SeekToTime(uint32 Time); + + + void cleanup(); + bool resetStream(); + + // video properties + TVideoPlayback _playbackType; + int _posX; + int _posY; + float _playZoom; + int _volume; + + bool _looping; + bool _dontDropFrames; + bool _freezeGame; + uint32 _currentTime; + + +private: + // seeking support + bool _seekingKeyframe; + float _timeOffset; + + bool _frameRendered; + + bool getIsFrameReady() { + return _videoFrameReady; + } +private: + bool _audioFrameReady; + bool _videoFrameReady; + float _videobufTime; + + bool WriteVideo(); + + bool _playbackStarted; + + // helpers + void SetDefaults(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp index 220e9f4057..2a651baabf 100644 --- a/engines/wintermute/wintermute.cpp +++ b/engines/wintermute/wintermute.cpp @@ -31,13 +31,13 @@ #include "common/fs.h" #include "engines/util.h" -#include "engines/wintermute/ad/AdGame.h" +#include "engines/wintermute/ad/ad_game.h" #include "engines/wintermute/wintermute.h" #include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/BRegistry.h" +#include "engines/wintermute/base/base_registry.h" -#include "engines/wintermute/base/BSoundMgr.h" -#include "engines/wintermute/base/scriptables/ScEngine.h" +#include "engines/wintermute/base/sound/base_sound_manager.h" +#include "engines/wintermute/base/scriptables/script_engine.h" namespace WinterMute { -- cgit v1.2.3