summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml6
-rw-r--r--CONTRIBUTING.md59
-rw-r--r--ISSUE_TEMPLATE10
-rw-r--r--LICENSE.md48
-rw-r--r--README.md8
-rw-r--r--bin/tests/test_math.cpp81
-rw-r--r--bin/tests/test_string.cpp4
-rw-r--r--core/bind/core_bind.cpp39
-rw-r--r--core/bind/core_bind.h7
-rw-r--r--core/color.cpp12
-rw-r--r--core/command_queue_mt.h4
-rw-r--r--core/global_constants.cpp17
-rw-r--r--core/globals.cpp8
-rw-r--r--core/io/http_client.cpp8
-rw-r--r--core/io/resource_format_xml.cpp1
-rw-r--r--core/math/aabb.h18
-rw-r--r--core/math/octree.h12
-rw-r--r--core/method_bind.h1
-rw-r--r--core/os/file_access.cpp6
-rw-r--r--core/os/file_access.h2
-rw-r--r--core/os/input_event.cpp4
-rw-r--r--core/os/input_event.h2
-rw-r--r--core/os/keyboard.cpp2
-rw-r--r--core/os/keyboard.h2
-rw-r--r--core/os/memory.h8
-rw-r--r--core/os/os.cpp8
-rw-r--r--core/os/os.h10
-rw-r--r--core/os/thread.cpp4
-rw-r--r--core/os/thread.h6
-rw-r--r--core/typedefs.h32
-rw-r--r--core/ustring.cpp31
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant_parser.cpp7
-rw-r--r--core/vector.h35
-rw-r--r--demos/2d/platformer/stage.xml156
-rw-r--r--demos/3d/polygon_path_finder/engine.cfg5
-rw-r--r--demos/3d/polygon_path_finder/icon.pngbin712 -> 0 bytes
-rw-r--r--demos/3d/polygon_path_finder/poly_with_holes.scnbin2974 -> 0 bytes
-rw-r--r--demos/3d/polygon_path_finder/polygonpathfinder.gd77
-rw-r--r--doc/Makefile2
-rw-r--r--doc/base/classes.xml639
-rw-r--r--doc/tools/makerst.py518
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp12
-rw-r--r--drivers/nrex/regex.cpp9
-rw-r--r--drivers/nrex/regex.h1
-rw-r--r--drivers/register_driver_types.cpp1
-rw-r--r--drivers/theora/video_stream_theora.cpp3
-rw-r--r--drivers/unix/memory_pool_static_malloc.cpp29
-rw-r--r--drivers/unix/thread_posix.cpp17
-rw-r--r--drivers/unix/thread_posix.h5
-rw-r--r--main/input_default.cpp203
-rw-r--r--main/input_default.h8
-rw-r--r--main/main.cpp8
-rw-r--r--modules/gdscript/gd_editor.cpp29
-rw-r--r--modules/gdscript/gd_script.cpp64
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotLib.java2
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotView.java237
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java140
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java107
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java211
-rw-r--r--platform/android/java_glue.cpp75
-rw-r--r--platform/android/java_glue.h2
-rw-r--r--platform/android/os_android.cpp33
-rw-r--r--platform/android/os_android.h21
-rw-r--r--platform/bb10/os_bb10.cpp4
-rw-r--r--platform/bb10/os_bb10.h2
-rw-r--r--platform/haiku/key_mapping_haiku.cpp2
-rwxr-xr-xplatform/iphone/gl_view.mm71
-rw-r--r--platform/iphone/os_iphone.cpp22
-rw-r--r--platform/iphone/os_iphone.h8
-rw-r--r--platform/iphone/xcode/godot_xcode/data.pck0
-rwxr-xr-xplatform/iphone/xcode/godot_xcode/godot_debug.iphone0
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj370
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.pngbin0 -> 529 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-667h.pngbin0 -> 648 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-667h@2x.pngbin0 -> 782 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-736h.pngbin0 -> 1641 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-736h@3x.pngbin0 -> 2547 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape-736h.pngbin0 -> 2547 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.pngbin0 -> 3096 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape~ipad.pngbin0 -> 599 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.pngbin0 -> 3035 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait~ipad.pngbin0 -> 554 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default@2x~iphone.pngbin0 -> 480 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Default~iphone.pngbin0 -> 274 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json128
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.pngbin0 -> 215 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.pngbin0 -> 218 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.pngbin0 -> 218 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.pngbin0 -> 224 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.pngbin0 -> 225 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.pngbin0 -> 230 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.pngbin0 -> 207 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.pngbin0 -> 205 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.pngbin0 -> 208 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.pngbin0 -> 208 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.pngbin0 -> 208 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.pngbin0 -> 209 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.pngbin0 -> 209 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.pngbin0 -> 211 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.pngbin0 -> 210 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.pngbin0 -> 227 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.pngbin0 -> 212 bytes
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes17
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings2
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/godot_ios-Info.plist50
-rw-r--r--platform/iphone/xcode/godot_xcode/godot_ios/main.m (renamed from core/os/pc_joystick_map.h)63
-rwxr-xr-xplatform/iphone/xcode/godot_xcode/godot_opt.iphone0
-rw-r--r--platform/nacl/nacl_keycodes.h2
-rw-r--r--platform/osx/audio_driver_osx.cpp3
-rw-r--r--platform/osx/os_osx.mm17
-rw-r--r--platform/windows/detect.py4
-rw-r--r--platform/windows/export/export.cpp343
-rw-r--r--platform/windows/export/export.h33
-rw-r--r--platform/windows/joystick.cpp2
-rw-r--r--platform/windows/key_mapping_win.cpp2
-rw-r--r--platform/windows/os_windows.cpp24
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--platform/winrt/os_winrt.cpp1
-rw-r--r--platform/x11/detect.py28
-rw-r--r--platform/x11/joystick_linux.cpp276
-rw-r--r--platform/x11/joystick_linux.h7
-rw-r--r--platform/x11/key_mapping_x11.cpp2
-rw-r--r--platform/x11/os_x11.cpp21
-rw-r--r--platform/x11/os_x11.h2
-rw-r--r--scene/2d/navigation_polygon.cpp4
-rw-r--r--scene/2d/tile_map.cpp11
-rw-r--r--scene/2d/tile_map.h1
-rw-r--r--scene/3d/camera.cpp23
-rw-r--r--scene/3d/particles.cpp4
-rw-r--r--scene/animation/animation_player.cpp12
-rw-r--r--scene/audio/event_player.cpp2
-rw-r--r--scene/audio/stream_player.cpp16
-rw-r--r--scene/audio/stream_player.h1
-rw-r--r--scene/gui/color_picker.cpp125
-rw-r--r--scene/gui/color_picker.h8
-rw-r--r--scene/gui/control.cpp13
-rw-r--r--scene/gui/graph_edit.cpp106
-rw-r--r--scene/gui/graph_edit.h13
-rw-r--r--scene/gui/graph_node.cpp1
-rw-r--r--scene/gui/item_list.cpp29
-rw-r--r--scene/gui/line_edit.cpp9
-rw-r--r--scene/gui/tabs.cpp1
-rw-r--r--scene/gui/text_edit.cpp6
-rw-r--r--scene/gui/tree.cpp30
-rw-r--r--scene/gui/tree.h6
-rw-r--r--scene/gui/video_player.cpp2
-rw-r--r--scene/main/timer.cpp1
-rw-r--r--scene/main/viewport.cpp47
-rw-r--r--scene/main/viewport.h6
-rw-r--r--scene/resources/default_theme/default_theme.cpp11
-rw-r--r--scene/resources/default_theme/icon_zoom_less.pngbin0 -> 390 bytes
-rw-r--r--scene/resources/default_theme/icon_zoom_more.pngbin0 -> 388 bytes
-rw-r--r--scene/resources/default_theme/icon_zoom_reset.pngbin0 -> 311 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h15
-rw-r--r--scene/resources/packed_scene.cpp32
-rw-r--r--scene/resources/packed_scene.h11
-rw-r--r--scene/resources/sample.cpp2
-rw-r--r--scene/resources/scene_format_text.cpp39
-rw-r--r--servers/audio/audio_server_sw.cpp3
-rw-r--r--servers/physics_2d/space_2d_sw.cpp4
-rw-r--r--servers/physics_2d/space_2d_sw.h2
-rw-r--r--servers/physics_2d_server.h2
-rw-r--r--servers/register_server_types.cpp4
-rw-r--r--tools/SCsub1
-rw-r--r--tools/doc/doc_data.cpp2
-rw-r--r--tools/docker/Dockerfile13
-rw-r--r--tools/docker/README.md40
-rw-r--r--tools/docker/scripts/install-android-tools90
-rw-r--r--tools/editor/animation_editor.cpp84
-rw-r--r--tools/editor/animation_editor.h4
-rw-r--r--tools/editor/editor_file_system.cpp2
-rw-r--r--tools/editor/editor_help.cpp2
-rw-r--r--tools/editor/editor_import_export.cpp46
-rw-r--r--tools/editor/editor_import_export.h4
-rw-r--r--tools/editor/editor_node.cpp74
-rw-r--r--tools/editor/editor_node.h5
-rw-r--r--tools/editor/editor_settings.cpp55
-rw-r--r--tools/editor/editor_settings.h3
-rw-r--r--tools/editor/icons/icon_array_data.pngbin212 -> 176 bytes
-rw-r--r--tools/editor/icons/icon_array_float.pngbin213 -> 177 bytes
-rw-r--r--tools/editor/icons/icon_array_int.pngbin204 -> 172 bytes
-rw-r--r--tools/editor/icons/icon_array_string.pngbin217 -> 178 bytes
-rw-r--r--tools/editor/icons/icon_array_variant.pngbin209 -> 172 bytes
-rw-r--r--tools/editor/icons/icon_bool.pngbin147 -> 164 bytes
-rw-r--r--tools/editor/icons/icon_color.pngbin322 -> 301 bytes
-rw-r--r--tools/editor/icons/icon_integer.pngbin142 -> 162 bytes
-rw-r--r--tools/editor/icons/icon_quat.pngbin265 -> 239 bytes
-rw-r--r--tools/editor/icons/icon_real.pngbin146 -> 162 bytes
-rw-r--r--tools/editor/icons/icon_rect2.pngbin240 -> 193 bytes
-rw-r--r--tools/editor/icons/icon_rect3.pngbin230 -> 202 bytes
-rw-r--r--tools/editor/icons/icon_reload_empty.pngbin0 -> 251 bytes
-rw-r--r--tools/editor/icons/icon_reload_small.pngbin0 -> 447 bytes
-rw-r--r--tools/editor/icons/icon_string.pngbin121 -> 136 bytes
-rw-r--r--tools/editor/icons/icon_vector.pngbin158 -> 183 bytes
-rw-r--r--tools/editor/icons/icon_vector2.pngbin141 -> 172 bytes
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.cpp8
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.cpp23
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp9
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp29
-rw-r--r--tools/editor/plugins/script_editor_plugin.h2
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp24
-rw-r--r--tools/editor/project_export.cpp31
-rw-r--r--tools/editor/project_export.h5
-rw-r--r--tools/editor/project_manager.cpp6
-rw-r--r--tools/editor/project_settings.cpp185
-rw-r--r--tools/editor/project_settings.h7
-rw-r--r--tools/editor/property_editor.cpp48
-rw-r--r--tools/editor/scene_tree_editor.cpp7
-rw-r--r--tools/editor/settings_config_dialog.cpp6
-rw-r--r--tools/pe_bliss/README84
-rw-r--r--tools/pe_bliss/SCsub5
-rw-r--r--tools/pe_bliss/entropy.cpp111
-rw-r--r--tools/pe_bliss/entropy.h51
-rw-r--r--tools/pe_bliss/file_version_info.cpp440
-rw-r--r--tools/pe_bliss/file_version_info.h199
-rw-r--r--tools/pe_bliss/message_table.cpp81
-rw-r--r--tools/pe_bliss/message_table.h56
-rw-r--r--tools/pe_bliss/pe_base.cpp1680
-rw-r--r--tools/pe_bliss/pe_base.h544
-rw-r--r--tools/pe_bliss/pe_bliss.h39
-rw-r--r--tools/pe_bliss/pe_bliss_godot.cpp118
-rw-r--r--tools/pe_bliss/pe_bliss_godot.h7
-rw-r--r--tools/pe_bliss/pe_bliss_resources.h36
-rw-r--r--tools/pe_bliss/pe_bound_import.cpp311
-rw-r--r--tools/pe_bliss/pe_bound_import.h108
-rw-r--r--tools/pe_bliss/pe_checksum.cpp103
-rw-r--r--tools/pe_bliss/pe_checksum.h30
-rw-r--r--tools/pe_bliss/pe_debug.cpp865
-rw-r--r--tools/pe_bliss/pe_debug.h324
-rw-r--r--tools/pe_bliss/pe_directory.cpp59
-rw-r--r--tools/pe_bliss/pe_directory.h50
-rw-r--r--tools/pe_bliss/pe_dotnet.cpp186
-rw-r--r--tools/pe_bliss/pe_dotnet.h97
-rw-r--r--tools/pe_bliss/pe_exception.cpp40
-rw-r--r--tools/pe_bliss/pe_exception.h130
-rw-r--r--tools/pe_bliss/pe_exception_directory.cpp177
-rw-r--r--tools/pe_bliss/pe_exception_directory.h88
-rw-r--r--tools/pe_bliss/pe_exports.cpp700
-rw-r--r--tools/pe_bliss/pe_exports.h184
-rw-r--r--tools/pe_bliss/pe_factory.cpp43
-rw-r--r--tools/pe_bliss/pe_factory.h39
-rw-r--r--tools/pe_bliss/pe_imports.cpp777
-rw-r--r--tools/pe_bliss/pe_imports.h208
-rw-r--r--tools/pe_bliss/pe_load_config.cpp557
-rw-r--r--tools/pe_bliss/pe_load_config.h184
-rw-r--r--tools/pe_bliss/pe_properties.cpp41
-rw-r--r--tools/pe_bliss/pe_properties.h236
-rw-r--r--tools/pe_bliss/pe_properties_generic.cpp645
-rw-r--r--tools/pe_bliss/pe_properties_generic.h277
-rw-r--r--tools/pe_bliss/pe_rebuilder.cpp214
-rw-r--r--tools/pe_bliss/pe_rebuilder.h40
-rw-r--r--tools/pe_bliss/pe_relocations.cpp320
-rw-r--r--tools/pe_bliss/pe_relocations.h122
-rw-r--r--tools/pe_bliss/pe_resource_manager.cpp286
-rw-r--r--tools/pe_bliss/pe_resource_manager.h113
-rw-r--r--tools/pe_bliss/pe_resource_viewer.cpp382
-rw-r--r--tools/pe_bliss/pe_resource_viewer.h153
-rw-r--r--tools/pe_bliss/pe_resources.cpp726
-rw-r--r--tools/pe_bliss/pe_resources.h245
-rw-r--r--tools/pe_bliss/pe_rich_data.cpp152
-rw-r--r--tools/pe_bliss/pe_rich_data.h58
-rw-r--r--tools/pe_bliss/pe_section.cpp303
-rw-r--r--tools/pe_bliss/pe_section.h158
-rw-r--r--tools/pe_bliss/pe_structures.h1028
-rw-r--r--tools/pe_bliss/pe_tls.cpp396
-rw-r--r--tools/pe_bliss/pe_tls.h122
-rw-r--r--tools/pe_bliss/resource_bitmap_reader.cpp86
-rw-r--r--tools/pe_bliss/resource_bitmap_reader.h50
-rw-r--r--tools/pe_bliss/resource_bitmap_writer.cpp75
-rw-r--r--tools/pe_bliss/resource_bitmap_writer.h47
-rw-r--r--tools/pe_bliss/resource_cursor_icon_reader.cpp521
-rw-r--r--tools/pe_bliss/resource_cursor_icon_reader.h84
-rw-r--r--tools/pe_bliss/resource_cursor_icon_writer.cpp447
-rw-r--r--tools/pe_bliss/resource_cursor_icon_writer.h94
-rw-r--r--tools/pe_bliss/resource_data_info.cpp48
-rw-r--r--tools/pe_bliss/resource_data_info.h48
-rw-r--r--tools/pe_bliss/resource_internal.h34
-rw-r--r--tools/pe_bliss/resource_message_list_reader.cpp131
-rw-r--r--tools/pe_bliss/resource_message_list_reader.h49
-rw-r--r--tools/pe_bliss/resource_string_table_reader.cpp109
-rw-r--r--tools/pe_bliss/resource_string_table_reader.h57
-rw-r--r--tools/pe_bliss/resource_version_info_reader.cpp311
-rw-r--r--tools/pe_bliss/resource_version_info_reader.h67
-rw-r--r--tools/pe_bliss/resource_version_info_writer.cpp283
-rw-r--r--tools/pe_bliss/resource_version_info_writer.h52
-rw-r--r--tools/pe_bliss/stdint_defs.h45
-rw-r--r--tools/pe_bliss/utils.cpp85
-rw-r--r--tools/pe_bliss/utils.h105
-rw-r--r--tools/pe_bliss/version_info_editor.cpp184
-rw-r--r--tools/pe_bliss/version_info_editor.h79
-rw-r--r--tools/pe_bliss/version_info_types.h38
-rw-r--r--tools/pe_bliss/version_info_viewer.cpp180
-rw-r--r--tools/pe_bliss/version_info_viewer.h89
-rw-r--r--tools/scripts/sort-demos.sh29
-rw-r--r--tools/steam/community_capsule.jpgbin0 -> 5571 bytes
-rw-r--r--tools/steam/community_capsule.pngbin0 -> 7263 bytes
-rw-r--r--tools/steam/header.pngbin0 -> 18980 bytes
-rw-r--r--tools/steam/icon32.icns1029
-rw-r--r--tools/steam/icon32.icobin0 -> 4286 bytes
-rw-r--r--tools/steam/icons.zipbin0 -> 114972 bytes
-rw-r--r--tools/steam/large_capsule.pngbin0 -> 19020 bytes
-rw-r--r--tools/steam/main_capsule.pngbin0 -> 25359 bytes
-rw-r--r--tools/steam/make_icons.sh7
-rw-r--r--tools/steam/small_capsule.pngbin0 -> 9144 bytes
-rw-r--r--version.py2
308 files changed, 5229 insertions, 20016 deletions
diff --git a/.gitignore b/.gitignore
index a6d5a2d412..92516285b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,8 @@ doc/_build/
*.bc
# Android specific
+platform/android/java/.gradle
+platform/android/java/.gradletasknamecache
platform/android/java/local.properties
platform/android/java/project.properties
platform/android/java/AndroidManifest.xml
diff --git a/.travis.yml b/.travis.yml
index 13f91b99e8..032e6aa0b8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -32,14 +32,18 @@ matrix:
env: GODOT_TARGET=windows
- compiler: gcc
env: GODOT_TARGET=iphone
+ - compiler: gcc
+ env: GODOT_TARGET=osx
- compiler: clang
env: GODOT_TARGET=android
- compiler: clang
env: GODOT_TARGET=windows
+ - compiler: clang
+ env: GODOT_TARGET=x11
before_script:
- - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; sudo apt-get install -y scons pkg-config libx11-dev libxcursor-dev build-essential libasound2-dev libfreetype6-dev libgl1-mesa-dev libglu-dev libssl-dev libxinerama-dev libevdev-dev libudev-dev; fi
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; sudo apt-get install -y scons pkg-config libx11-dev libxcursor-dev build-essential libasound2-dev libfreetype6-dev libgl1-mesa-dev libglu-dev libssl-dev libxinerama-dev libudev-dev; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$GODOT_TARGET" = "windows" ]; then sudo apt-get update -qq; sudo apt-get install -y mingw32 mingw-w64; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew install scons; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then brew update; brew install android-sdk android-ndk; export ANDROID_HOME=/usr/local/opt/android-sdk; export ANDROID_NDK_ROOT=/usr/local/opt/android-ndk; fi
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..887fe93779
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,59 @@
+# How to contribute efficiently
+
+**Please read the first section before reporting a bug!**
+
+## Reporting bugs or proposing features
+
+The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
+
+Everything refered to hereafter as "bug" also applies for feature requests.
+
+If you are reporting a new issue, you will make our life much simpler (and the fix come much sooner) by following those guidelines:
+
+#### Search first in the existing database
+
+Issues are often reported several times by various users. It's a good practice to **search first** in the issues database before reporting your issue. If you don't find a relevant match or if you are unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
+
+#### Specify the platform
+
+Godot runs on a large variety of platforms and operating systems and devices. If you believe your issue is device/platform dependent (for example if it is related to the rendering, crashes or compilation errors), please specify:
+* Operating system
+* Device (including architecture, e.g. x86, x86_64, arm, etc.)
+* GPU model (and driver in use if you know it)
+
+#### Specify steps to reproduce
+
+Many bugs can't be reproduced unless specific steps are taken. Please **specify the exact steps** that must be taken to reproduce the condition, and try to keep them as minimal as possible.
+
+#### Provide a simple, example project
+
+Sometimes an unexpected behavior happens in your project. In such case, understand that:
+
+* What happens to you may not happen to other users.
+* We can't take the time to look at your project, understand how it is set up and then figure out why it's failing.
+
+To speed up our work, please prepare for us **a simple project** that isolates and reproduces the issue. This is always the **the best way for us to fix it**. You can attach a zip file with the minimal project directly to the bug report, by drag and dropping the file in the GitHub edition field.
+
+## Contributing pull requests
+
+If you want to add new engine functionalities, please make sure that:
+
+* This functionality is desired.
+* You talked to other developers on how to implement it best (on either communication channel, and maybe in a GitHub issue first before making your PR).
+* Even if it does not get merged, your PR is useful for future work by another developer.
+
+Similar rules can be applied when contributing bug fixes - it's always best to discuss the implementation in the bug report first if you are not 100% about what would be the best fix.
+
+#### Be nice to the git history
+
+Try to make simple PRs with that handle one specific topic. Just like for reporting issues, it's better to open 3 different PRs that each address a different issue than one big PR with three commits.
+
+When updating your fork with upstream changes, please use ``git pull --rebase`` to avoid creating "merge commits". Those commits unnecessarily pollute the git history when coming from PRs.
+
+Also try to make commits that bring the engine from one stable state to another stable state, i.e. if your first commit has a bug that you fixed in the second commit, try to merge them together before making your pull request (see ``git rebase -i`` and relevant help about rebasing or ammending commits on the Internet).
+
+This git style guide has some good practices to have in mind: https://github.com/agis-/git-style-guide
+
+Thanks!
+
+The Godot development team
diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE
new file mode 100644
index 0000000000..06fa7b316d
--- /dev/null
+++ b/ISSUE_TEMPLATE
@@ -0,0 +1,10 @@
+**Operating system or device:**
+
+
+**Issue description** (what happened, and what was expected):
+
+
+**Steps to reproduce:**
+
+
+**Link to minimal example project** (optional but very welcome):
diff --git a/LICENSE.md b/LICENSE.md
index 2f78f0e37d..2f3e879c8c 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,27 +1,27 @@
- GODOT ENGINE
- http://www.godotengine.org
-**********************************************************************
- Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ GODOT ENGINE
+ http://www.godotengine.org
+
+************************************************************************
+
+ Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
-**********************************************************************
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+************************************************************************
diff --git a/README.md b/README.md
index d5dadb93a7..2586a5ea0d 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
![GODOT](/logo.png)
+http://www.godotengine.org
+
### The Engine
Godot is a fully featured, open source, MIT licensed, game engine. It focuses on having great tools, and a visual oriented workflow that can export to PC, Mobile and Web platforms with no hassle.
@@ -11,7 +13,7 @@ Godot has been developed by Juan Linietsky and Ariel Manzur for several years, a
### Documentation
-Documentation has been moved to the [OpenProject Wiki](http://godotengine.org/projects/godot-engine/wiki/Documentation).
+Documentation has been moved to [ReadTheDocs](http://docs.godotengine.org).
### Binary Downloads, Community, etc.
@@ -22,4 +24,6 @@ http://www.godotengine.org
### Compiling from Source
Compilation instructions for every platform can be found in the Wiki:
-http://godotengine.org/projects/godot-engine/wiki/Advanced_topics
+http://docs.godotengine.org/en/latest/reference/_compiling.html
+
+[![Build Status](https://travis-ci.org/godotengine/godot.svg?branch=master)](https://travis-ci.org/godotengine/godot)
diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp
index b5041b265f..05acd5c1ec 100644
--- a/bin/tests/test_math.cpp
+++ b/bin/tests/test_math.cpp
@@ -75,9 +75,90 @@ fix: 0, 0, 100, 100
}
+uint32_t ihash( uint32_t a)
+{
+ a = (a+0x7ed55d16) + (a<<12);
+ a = (a^0xc761c23c) ^ (a>>19);
+ a = (a+0x165667b1) + (a<<5);
+ a = (a+0xd3a2646c) ^ (a<<9);
+ a = (a+0xfd7046c5) + (a<<3);
+ a = (a^0xb55a4f09) ^ (a>>16);
+ return a;
+}
+
+uint32_t ihash2( uint32_t a) {
+ a = (a ^ 61) ^ (a >> 16);
+ a = a + (a << 3);
+ a = a ^ (a >> 4);
+ a = a * 0x27d4eb2d;
+ a = a ^ (a >> 15);
+ return a;
+}
+
+uint32_t ihash3( uint32_t a)
+{
+ a = (a+0x479ab41d) + (a<<8);
+ a = (a^0xe4aa10ce) ^ (a>>5);
+ a = (a+0x9942f0a6) - (a<<14);
+ a = (a^0x5aedd67d) ^ (a>>3);
+ a = (a+0x17bea992) + (a<<7);
+ return a;
+}
MainLoop* test() {
+
+ {
+
+ Vector<int32_t> hashes;
+ List<StringName> tl;
+ ObjectTypeDB::get_type_list(&tl);
+
+
+ for (List<StringName>::Element *E=tl.front();E;E=E->next()) {
+
+ Vector<uint8_t> m5b = E->get().operator String().md5_buffer();
+ uint32_t *ub = (uint32_t*)m5b.ptr();
+ //hashes.push_back(ihash(ihash2(ihash3(*ub))));
+ hashes.push_back(hashes.size());
+ //hashes.push_back(E->get().hash());
+
+ }
+
+ //hashes.resize(50);
+
+ for(int i=nearest_shift(hashes.size());i<20;i++) {
+
+ bool success=true;
+ for(int s=0;s<10000;s++) {
+ Set<uint32_t> existing;
+ success=true;
+
+ for(int j=0;j<hashes.size();j++) {
+
+ uint32_t eh = ihash2(ihash3(hashes[j]+ihash(s)+s))&((1<<i)-1);
+ if (existing.has(eh)) {
+ success=false;
+ break;
+ }
+ existing.insert(eh);
+ }
+
+ if (success) {
+ print_line("success at "+itos(i)+"/"+itos(nearest_shift(hashes.size()))+" shift "+itos(s));
+ break;
+ }
+ }
+ if (success)
+ break;
+ }
+
+ print_line("DONE");
+
+
+
+ return NULL;
+ }
{
diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp
index fe7bf4d9cf..27707b1a00 100644
--- a/bin/tests/test_string.cpp
+++ b/bin/tests/test_string.cpp
@@ -472,7 +472,7 @@ bool test_26() {
{
printf("%ls\n", regexp.get_capture(i).c_str());
}
- return res;
+ return (res>=0);
};
struct test_27_data {
@@ -904,7 +904,7 @@ MainLoop* test() {
OS::get_singleton()->print("***TOTALS!***\n");
OS::get_singleton()->print("*************\n");
- OS::get_singleton()->print("Passed %i of %i tests\n",count,passed);
+ OS::get_singleton()->print("Passed %i of %i tests\n", passed, count);
return NULL;
}
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 94d9e22a1e..229640ba11 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -390,6 +390,12 @@ bool _OS::is_ok_left_and_cancel_right() const {
return OS::get_singleton()->get_swap_ok_cancel();
}
+Error _OS::set_thread_name(const String& p_name) {
+
+ return Thread::set_name(p_name);
+};
+
+
/*
enum Weekday {
DAY_SUNDAY,
@@ -683,6 +689,10 @@ void _OS::native_video_pause() {
OS::get_singleton()->native_video_pause();
};
+void _OS::native_video_unpause() {
+ OS::get_singleton()->native_video_unpause();
+};
+
void _OS::native_video_stop() {
OS::get_singleton()->native_video_stop();
@@ -868,6 +878,7 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("native_video_is_playing"),&_OS::native_video_is_playing);
ObjectTypeDB::bind_method(_MD("native_video_stop"),&_OS::native_video_stop);
ObjectTypeDB::bind_method(_MD("native_video_pause"),&_OS::native_video_pause);
+ ObjectTypeDB::bind_method(_MD("native_video_unpause"),&_OS::native_video_unpause);
ObjectTypeDB::bind_method(_MD("get_scancode_string","code"),&_OS::get_scancode_string);
ObjectTypeDB::bind_method(_MD("is_scancode_unicode","code"),&_OS::is_scancode_unicode);
@@ -877,6 +888,8 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("alert","text","title"),&_OS::alert,DEFVAL("Alert!"));
+ ObjectTypeDB::bind_method(_MD("set_thread_name","name"),&_OS::set_thread_name);
+
BIND_CONSTANT( DAY_SUNDAY );
BIND_CONSTANT( DAY_MONDAY );
@@ -1313,9 +1326,9 @@ String _File::get_line() const{
}
-Vector<String> _File::get_csv_line() const {
+Vector<String> _File::get_csv_line(String delim) const {
ERR_FAIL_COND_V(!f,Vector<String>());
- return f->get_csv_line();
+ return f->get_csv_line(delim);
}
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
@@ -1498,7 +1511,7 @@ void _File::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_endian_swap","enable"),&_File::set_endian_swap);
ObjectTypeDB::bind_method(_MD("get_error:Error"),&_File::get_error);
ObjectTypeDB::bind_method(_MD("get_var"),&_File::get_var);
- ObjectTypeDB::bind_method(_MD("get_csv_line"),&_File::get_csv_line);
+ ObjectTypeDB::bind_method(_MD("get_csv_line","delim"),&_File::get_csv_line,DEFVAL(","));
ObjectTypeDB::bind_method(_MD("store_8","value"),&_File::store_8);
ObjectTypeDB::bind_method(_MD("store_16","value"),&_File::store_16);
@@ -1895,13 +1908,7 @@ void _Thread::_start_func(void *ud) {
Variant::CallError ce;
const Variant* arg[1]={&t->userdata};
- // we don't know our thread pointer yet :(
- if (t->name == "") {
- // come up with a better name using maybe the filename on the Script?
- //t->thread->set_name(t->target_method);
- } else {
- //t->thread->set_name(t->name);
- };
+ Thread::set_name(t->target_method);
t->ret=t->target_instance->call(t->target_method,arg,1,ce);
if (ce.error!=Variant::CallError::CALL_OK) {
@@ -1992,24 +1999,12 @@ Variant _Thread::wait_to_finish() {
return r;
}
-Error _Thread::set_name(const String &p_name) {
-
- name = p_name;
-
- if (thread) {
- return thread->set_name(p_name);
- };
-
- return OK;
-};
-
void _Thread::_bind_methods() {
ObjectTypeDB::bind_method(_MD("start:Error","instance","method","userdata","priority"),&_Thread::start,DEFVAL(Variant()),DEFVAL(PRIORITY_NORMAL));
ObjectTypeDB::bind_method(_MD("get_id"),&_Thread::get_id);
ObjectTypeDB::bind_method(_MD("is_active"),&_Thread::is_active);
ObjectTypeDB::bind_method(_MD("wait_to_finish:Variant"),&_Thread::wait_to_finish);
- ObjectTypeDB::bind_method(_MD("set_name:Error", "name"),&_Thread::set_name);
BIND_CONSTANT( PRIORITY_LOW );
BIND_CONSTANT( PRIORITY_NORMAL );
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index e03657f3a0..4a9bb2a961 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -131,6 +131,7 @@ public:
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
bool native_video_is_playing();
void native_video_pause();
+ void native_video_unpause();
void native_video_stop();
void set_iterations_per_second(int p_ips);
@@ -270,6 +271,8 @@ public:
bool is_ok_left_and_cancel_right() const;
+ Error set_thread_name(const String& p_name);
+
static _OS *get_singleton() { return singleton; }
_OS();
@@ -390,7 +393,7 @@ public:
virtual void store_pascal_string(const String& p_string);
virtual String get_pascal_string();
- Vector<String> get_csv_line() const;
+ Vector<String> get_csv_line(String delim=",") const;
void store_buffer(const DVector<uint8_t>& p_buffer); ///< store an array of bytes
@@ -512,7 +515,6 @@ protected:
Object *target_instance;
StringName target_method;
Thread *thread;
- String name;
static void _bind_methods();
static void _start_func(void *ud);
public:
@@ -528,7 +530,6 @@ public:
String get_id() const;
bool is_active() const;
Variant wait_to_finish();
- Error set_name(const String& p_name);
_Thread();
~_Thread();
diff --git a/core/color.cpp b/core/color.cpp
index c53de360bc..56a550c024 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -117,29 +117,31 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
}
p_h *=6.0;
+ p_h = Math::fmod(p_h,6);
i = Math::floor( p_h );
+
f = p_h - i;
p = p_v * ( 1 - p_s );
q = p_v * ( 1 - p_s * f );
t = p_v * ( 1 - p_s * ( 1 - f ) );
switch( i ) {
- case 0:
+ case 0: // Red is the dominant color
r = p_v;
g = t;
b = p;
break;
- case 1:
+ case 1: // Green is the dominant color
r = q;
g = p_v;
b = p;
break;
- case 2:
+ case 2:
r = p;
g = p_v;
b = t;
break;
- case 3:
+ case 3: // Blue is the dominant color
r = p;
g = q;
b = p_v;
@@ -149,7 +151,7 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
g = p;
b = p_v;
break;
- default: // cap_se 5:
+ default: // (5) Red is the dominant color
r = p_v;
g = p;
b = q;
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index 4fd33e3a55..142668f6f6 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -34,7 +34,6 @@
#include "os/mutex.h"
#include "os/memory.h"
#include "simple_type.h"
-#include "print_string.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -175,7 +174,7 @@ class CommandQueueMT {
R* ret;
SyncSemaphore *sync;
- virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); print_line("post"); sync->in_use=false; ; }
+ virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; }
};
template<class T,class M,class P1,class P2,class R>
@@ -676,7 +675,6 @@ public:
if (sync) sync->post();
ss->sem->wait();
- print_line("wait");
}
template<class T, class M, class P1, class P2,class R>
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index 92e50a8b96..a183255b06 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -106,7 +106,7 @@ static _GlobalConstant _global_constants[]={
BIND_GLOBAL_CONSTANT( KEY_KP_ENTER ),
BIND_GLOBAL_CONSTANT( KEY_KP_MULTIPLY ),
BIND_GLOBAL_CONSTANT( KEY_KP_DIVIDE ),
- BIND_GLOBAL_CONSTANT( KEY_KP_SUBSTRACT ),
+ BIND_GLOBAL_CONSTANT( KEY_KP_SUBTRACT ),
BIND_GLOBAL_CONSTANT( KEY_KP_PERIOD ),
BIND_GLOBAL_CONSTANT( KEY_KP_ADD ),
BIND_GLOBAL_CONSTANT( KEY_KP_0 ),
@@ -317,16 +317,19 @@ static _GlobalConstant _global_constants[]={
BIND_GLOBAL_CONSTANT( KEY_MASK_KPAD ),
BIND_GLOBAL_CONSTANT( KEY_MASK_GROUP_SWITCH ),
- // joysticks
+ // mouse
BIND_GLOBAL_CONSTANT( BUTTON_LEFT ),
BIND_GLOBAL_CONSTANT( BUTTON_RIGHT ),
BIND_GLOBAL_CONSTANT( BUTTON_MIDDLE ),
BIND_GLOBAL_CONSTANT( BUTTON_WHEEL_UP ),
BIND_GLOBAL_CONSTANT( BUTTON_WHEEL_DOWN ),
+ BIND_GLOBAL_CONSTANT( BUTTON_WHEEL_LEFT ),
+ BIND_GLOBAL_CONSTANT( BUTTON_WHEEL_RIGHT ),
BIND_GLOBAL_CONSTANT( BUTTON_MASK_LEFT ),
BIND_GLOBAL_CONSTANT( BUTTON_MASK_RIGHT ),
BIND_GLOBAL_CONSTANT( BUTTON_MASK_MIDDLE ),
+ //joysticks
BIND_GLOBAL_CONSTANT( JOY_BUTTON_0 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_1 ),
BIND_GLOBAL_CONSTANT( JOY_BUTTON_2 ),
@@ -476,6 +479,16 @@ static _GlobalConstant _global_constants[]={
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR ),
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NETWORK ),
BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT ),
+
+ BIND_GLOBAL_CONSTANT( METHOD_FLAG_NORMAL ),
+ BIND_GLOBAL_CONSTANT( METHOD_FLAG_EDITOR ),
+ BIND_GLOBAL_CONSTANT( METHOD_FLAG_NOSCRIPT ),
+ BIND_GLOBAL_CONSTANT( METHOD_FLAG_CONST ),
+ BIND_GLOBAL_CONSTANT( METHOD_FLAG_REVERSE ),
+ BIND_GLOBAL_CONSTANT( METHOD_FLAG_VIRTUAL ),
+ BIND_GLOBAL_CONSTANT( METHOD_FLAG_FROM_SCRIPT ),
+ BIND_GLOBAL_CONSTANT( METHOD_FLAGS_DEFAULT ),
+
{"TYPE_NIL",Variant::NIL},
{"TYPE_BOOL",Variant::BOOL},
{"TYPE_INT",Variant::INT},
diff --git a/core/globals.cpp b/core/globals.cpp
index 5f52420735..d63f9c1bb4 100644
--- a/core/globals.cpp
+++ b/core/globals.cpp
@@ -916,6 +916,14 @@ static String _encode_variant(const Variant& p_variant) {
float val = p_variant;
return rtos(val)+(val==int(val)?".0":"");
} break;
+ case Variant::VECTOR2: {
+ Vector2 val = p_variant;
+ return String("Vector2(")+rtos(val.x)+String(", ")+rtos(val.y)+String(")");
+ } break;
+ case Variant::VECTOR3: {
+ Vector3 val = p_variant;
+ return String("Vector3(")+rtos(val.x)+ String(", ") +rtos(val.y)+ String(", ") +rtos(val.z)+String(")");
+ } break;
case Variant::STRING: {
String val = p_variant;
return "\""+val.xml_escape()+"\"";
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 19a7286dcf..b070e52f0a 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -306,8 +306,8 @@ Error HTTPClient::poll(){
for(int i=0;i<responses.size();i++) {
- String s = responses[i].strip_edges();
- s = s.to_lower();
+ String header = responses[i].strip_edges();
+ String s = header.to_lower();
if (s.length()==0)
continue;
if (s.begins_with("content-length:")) {
@@ -316,7 +316,7 @@ Error HTTPClient::poll(){
}
if (s.begins_with("transfer-encoding:")) {
- String encoding = s.substr(s.find(":")+1,s.length()).strip_edges();
+ String encoding = header.substr(header.find(":")+1,header.length()).strip_edges();
//print_line("TRANSFER ENCODING: "+encoding);
if (encoding=="chunked") {
chunked=true;
@@ -330,7 +330,7 @@ Error HTTPClient::poll(){
response_num=num.to_int();
} else {
- response_headers.push_back(s);
+ response_headers.push_back(header);
}
}
diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp
index 8c8d79948a..03b77a4aab 100644
--- a/core/io/resource_format_xml.cpp
+++ b/core/io/resource_format_xml.cpp
@@ -1796,6 +1796,7 @@ Error ResourceInteractiveLoaderXML::rename_dependencies(FileAccess *p_f, const S
fw->store_8(c);
c=f->get_8();
}
+ f->close();
bool all_ok = fw->get_error()==OK;
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 7c9c3081ac..0fada859c0 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -66,6 +66,7 @@ public:
bool operator!=(const AABB& p_rval) const;
_FORCE_INLINE_ bool intersects(const AABB& p_aabb) const; /// Both AABBs overlap
+ _FORCE_INLINE_ bool intersects_inclusive(const AABB& p_aabb) const; /// Both AABBs (or their faces) overlap
_FORCE_INLINE_ bool encloses(const AABB & p_aabb) const; /// p_aabb is completely inside this
AABB merge(const AABB& p_with) const;
@@ -126,6 +127,23 @@ inline bool AABB::intersects(const AABB& p_aabb) const {
return true;
}
+inline bool AABB::intersects_inclusive(const AABB& p_aabb) const {
+
+ if ( pos.x > (p_aabb.pos.x + p_aabb.size.x) )
+ return false;
+ if ( (pos.x+size.x) < p_aabb.pos.x )
+ return false;
+ if ( pos.y > (p_aabb.pos.y + p_aabb.size.y) )
+ return false;
+ if ( (pos.y+size.y) < p_aabb.pos.y )
+ return false;
+ if ( pos.z > (p_aabb.pos.z + p_aabb.size.z) )
+ return false;
+ if ( (pos.z+size.z) < p_aabb.pos.z )
+ return false;
+
+ return true;
+}
inline bool AABB::encloses(const AABB & p_aabb) const {
diff --git a/core/math/octree.h b/core/math/octree.h
index b51c4bcba7..69edf80e09 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -201,7 +201,7 @@ private:
_FORCE_INLINE_ void _pair_check(PairData *p_pair) {
- bool intersect=p_pair->A->aabb.intersects( p_pair->B->aabb );
+ bool intersect=p_pair->A->aabb.intersects_inclusive( p_pair->B->aabb );
if (intersect!=p_pair->intersect) {
@@ -480,7 +480,7 @@ void Octree<T,use_pairs,AL>::_insert_element(Element *p_element,Octant *p_octant
if (p_octant->children[i]) {
/* element exists, go straight to it */
- if (p_octant->children[i]->aabb.intersects( p_element->aabb ) ) {
+ if (p_octant->children[i]->aabb.intersects_inclusive( p_element->aabb ) ) {
_insert_element( p_element, p_octant->children[i] );
splits++;
}
@@ -497,7 +497,7 @@ void Octree<T,use_pairs,AL>::_insert_element(Element *p_element,Octant *p_octant
if (i&4)
aabb.pos.z+=aabb.size.z;
- if (aabb.intersects( p_element->aabb) ) {
+ if (aabb.intersects_inclusive( p_element->aabb) ) {
/* if actually intersects, create the child */
Octant *child = memnew_allocator( Octant, AL );
@@ -1146,7 +1146,7 @@ void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const AABB& p_aabb, T**
continue;
e->last_pass=pass;
- if (p_aabb.intersects(e->aabb)) {
+ if (p_aabb.intersects_inclusive(e->aabb)) {
if (*p_result_idx<p_result_max) {
@@ -1175,7 +1175,7 @@ void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const AABB& p_aabb, T**
continue;
e->last_pass=pass;
- if (p_aabb.intersects(e->aabb)) {
+ if (p_aabb.intersects_inclusive(e->aabb)) {
if (*p_result_idx<p_result_max) {
@@ -1193,7 +1193,7 @@ void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const AABB& p_aabb, T**
for (int i=0;i<8;i++) {
- if (p_octant->children[i] && p_octant->children[i]->aabb.intersects(p_aabb)) {
+ if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_inclusive(p_aabb)) {
_cull_AABB(p_octant->children[i],p_aabb, p_result_array,p_result_idx,p_result_max,p_subindex_array,p_mask);
}
}
diff --git a/core/method_bind.h b/core/method_bind.h
index 4c2598e50c..da3d7c1062 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -50,6 +50,7 @@ enum MethodFlags {
METHOD_FLAG_CONST=8,
METHOD_FLAG_REVERSE=16, // used for events
METHOD_FLAG_VIRTUAL=32,
+ METHOD_FLAG_FROM_SCRIPT=64,
METHOD_FLAGS_DEFAULT=METHOD_FLAG_NORMAL,
};
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index d82d0b63c5..68c9dee84d 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -277,7 +277,9 @@ String FileAccess::get_line() const {
return String::utf8(line.get_data());
}
-Vector<String> FileAccess::get_csv_line() const {
+Vector<String> FileAccess::get_csv_line(String delim) const {
+
+ ERR_FAIL_COND_V(delim.length()!=1,Vector<String>());
String l;
int qc=0;
@@ -303,7 +305,7 @@ Vector<String> FileAccess::get_csv_line() const {
CharType s[2]={0,0};
- if (!in_quote && c==',') {
+ if (!in_quote && c==delim[0]) {
strings.push_back(current);
current=String();
} else if (c=='"') {
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 51cf839117..3249e21ffb 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -102,7 +102,7 @@ public:
virtual int get_buffer(uint8_t *p_dst,int p_length) const; ///< get an array of bytes
virtual String get_line() const;
- virtual Vector<String> get_csv_line() const;
+ virtual Vector<String> get_csv_line(String delim=",") const;
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
* It's not about the current CPU type but file formats.
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 2f39567a7e..3022a56e2a 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -107,13 +107,13 @@ InputEvent::operator String() const {
} break;
case JOYSTICK_MOTION: {
- str+= "Event: JoyMotion ";
+ str+= "Event: JoystickMotion ";
str=str+"Axis: "+itos(joy_motion.axis)+" Value: " +rtos(joy_motion.axis_value);
return str;
} break;
case JOYSTICK_BUTTON: {
- str+= "Event: JoyButton ";
+ str+= "Event: JoystickButton ";
str=str+"Pressed: "+itos(joy_button.pressed)+" Index: " +itos(joy_button.button_index)+" pressure "+rtos(joy_button.pressure);
return str;
diff --git a/core/os/input_event.h b/core/os/input_event.h
index b601adc875..36c1556524 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -51,6 +51,8 @@ enum {
BUTTON_MIDDLE=3,
BUTTON_WHEEL_UP=4,
BUTTON_WHEEL_DOWN=5,
+ BUTTON_WHEEL_LEFT=6,
+ BUTTON_WHEEL_RIGHT=7,
BUTTON_MASK_LEFT=(1<<(BUTTON_LEFT-1)),
BUTTON_MASK_RIGHT=(1<<(BUTTON_RIGHT-1)),
BUTTON_MASK_MIDDLE=(1<<(BUTTON_MIDDLE-1)),
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index 633aa06a9a..4c0a074a07 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -82,7 +82,7 @@ static const _KeyCodeText _keycodes[]={
{KEY_KP_ENTER ,"Kp Enter"},
{KEY_KP_MULTIPLY ,"Kp Multiply"},
{KEY_KP_DIVIDE ,"Kp Divide"},
- {KEY_KP_SUBSTRACT ,"Kp Substract"},
+ {KEY_KP_SUBTRACT ,"Kp Subtract"},
{KEY_KP_PERIOD ,"Kp Period"},
{KEY_KP_ADD ,"Kp Add"},
{KEY_KP_0 ,"Kp 0"},
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 69e74d1252..0848f8c28e 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -98,7 +98,7 @@ enum KeyList {
KEY_KP_ENTER=SPKEY | 0x80,
KEY_KP_MULTIPLY=SPKEY | 0x81,
KEY_KP_DIVIDE=SPKEY | 0x82,
- KEY_KP_SUBSTRACT=SPKEY | 0x83,
+ KEY_KP_SUBTRACT=SPKEY | 0x83,
KEY_KP_PERIOD=SPKEY | 0x84,
KEY_KP_ADD=SPKEY | 0x85,
KEY_KP_0=SPKEY | 0x86,
diff --git a/core/os/memory.h b/core/os/memory.h
index 98b973bc06..8eb5ceccb6 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -308,11 +308,11 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
same strategy used by std::vector, and the DVector class, so it should be safe.*/
size_t len = sizeof(T) * p_elements;
- unsigned int *mem = (unsigned int*)Memory::alloc_static( len + DEFAULT_ALIGNMENT, p_descr );
+ unsigned int *mem = (unsigned int*)Memory::alloc_static( len + MAX(sizeof(size_t), DEFAULT_ALIGNMENT), p_descr );
T *failptr=0; //get rid of a warning
ERR_FAIL_COND_V( !mem, failptr );
*mem=p_elements;
- mem = (unsigned int *)( ((uint8_t*)mem) + DEFAULT_ALIGNMENT);
+ mem = (unsigned int *)( ((uint8_t*)mem) + MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
T* elems = (T*)mem;
/* call operator new */
@@ -331,14 +331,14 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
template<typename T>
size_t memarr_len(const T *p_class) {
- uint8_t* ptr = ((uint8_t*)p_class) - DEFAULT_ALIGNMENT;
+ uint8_t* ptr = ((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT);
return *(size_t*)ptr;
}
template<typename T>
void memdelete_arr(T *p_class) {
- unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - DEFAULT_ALIGNMENT);
+ unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
for (unsigned int i=0;i<*elems;i++) {
diff --git a/core/os/os.cpp b/core/os/os.cpp
index e93038f854..1aee6d9aa2 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -478,6 +478,10 @@ void OS::native_video_pause() {
};
+void OS::native_video_unpause() {
+
+};
+
void OS::native_video_stop() {
};
@@ -523,6 +527,10 @@ String OS::get_joy_guid(int p_device) const {
return "Default Joystick";
}
+void OS::set_context(int p_context) {
+
+}
+
OS::OS() {
last_error=NULL;
frames_drawn=0;
diff --git a/core/os/os.h b/core/os/os.h
index e53980a8fe..a80b81bfa2 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -173,6 +173,8 @@ public:
virtual bool is_window_maximized() const { return true; }
+
+
virtual void set_iterations_per_second(int p_ips);
virtual int get_iterations_per_second() const;
@@ -374,6 +376,7 @@ public:
virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
virtual bool native_video_is_playing() const;
virtual void native_video_pause();
+ virtual void native_video_unpause();
virtual void native_video_stop();
virtual bool can_use_threads() const;
@@ -402,6 +405,13 @@ public:
virtual bool is_joy_known(int p_device);
virtual String get_joy_guid(int p_device)const;
+ enum EngineContext {
+ CONTEXT_EDITOR,
+ CONTEXT_PROJECTMAN,
+ };
+
+ virtual void set_context(int p_context);
+
OS();
virtual ~OS();
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 7fb1e969d4..f5d984876d 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -32,6 +32,7 @@
Thread* (*Thread::create_func)(ThreadCreateCallback,void *,const Settings&)=NULL;
Thread::ID (*Thread::get_thread_ID_func)()=NULL;
void (*Thread::wait_to_finish_func)(Thread*)=NULL;
+Error (*Thread::set_name_func)(const String&)=NULL;
Thread::ID Thread::_main_thread_id=0;
@@ -60,6 +61,9 @@ void Thread::wait_to_finish(Thread *p_thread) {
Error Thread::set_name(const String &p_name) {
+ if (set_name_func)
+ return set_name_func(p_name);
+
return ERR_UNAVAILABLE;
};
diff --git a/core/os/thread.h b/core/os/thread.h
index 5711561809..4fead72b94 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -63,6 +63,7 @@ protected:
static Thread* (*create_func)(ThreadCreateCallback p_callback,void *,const Settings&);
static ID (*get_thread_ID_func)();
static void (*wait_to_finish_func)(Thread*);
+ static Error (*set_name_func)(const String&);
friend class Main;
@@ -73,10 +74,9 @@ protected:
public:
- virtual Error set_name(const String& p_name);
-
virtual ID get_ID() const=0;
-
+
+ static Error set_name(const String &p_name);
_FORCE_INLINE_ static ID get_main_ID() { return _main_thread_id; } ///< get the ID of the main thread
static ID get_caller_ID(); ///< get the ID of the caller function ID
static void wait_to_finish(Thread *p_thread); ///< waits until thread is finished, and deallocates it.
diff --git a/core/typedefs.h b/core/typedefs.h
index 1ca7a4f66d..48acca326e 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -74,7 +74,7 @@
#endif
#ifndef DEFAULT_ALIGNMENT
-#define DEFAULT_ALIGNMENT 16
+#define DEFAULT_ALIGNMENT 1
#endif
@@ -154,6 +154,23 @@ inline void __swap_tmpl(T &x, T &y ) {
((m_hex>='A' && m_hex<='F')?(10+m_hex-'A'):\
((m_hex>='a' && m_hex<='f')?(10+m_hex-'a'):0)))
+// Macro to check whether we are compiled by clang
+// and we have a specific builtin
+#if defined(__llvm__) && defined(__has_builtin)
+ #define _llvm_has_builtin(x) __has_builtin(x)
+#else
+ #define _llvm_has_builtin(x) 0
+#endif
+
+#if (defined(__GNUC__) && (__GNUC__ >= 5)) || _llvm_has_builtin(__builtin_mul_overflow)
+# define _mul_overflow __builtin_mul_overflow
+#endif
+
+#if (defined(__GNUC__) && (__GNUC__ >= 5)) || _llvm_has_builtin(__builtin_add_overflow)
+# define _add_overflow __builtin_add_overflow
+#endif
+
+
@@ -167,6 +184,19 @@ static _FORCE_INLINE_ unsigned int nearest_power_of_2(unsigned int x) {
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
+
+ return ++x;
+}
+
+template<class T>
+static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
+
+ --x;
+ // If the compiler is smart, it unrolls this loop
+ // If its dumb, this is a bit slow.
+ for (size_t i = 0; i < sizeof(T); i++)
+ x |= x >> (1 << i);
+
return ++x;
}
diff --git a/core/ustring.cpp b/core/ustring.cpp
index ee750c39e5..1017fc0ca3 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -507,26 +507,35 @@ String String::capitalize() const {
return cap;
}
-String String::camelcase_to_underscore() const {
+String String::camelcase_to_underscore(bool lowercase) const {
const CharType * cstr = c_str();
- String newString;
+ String new_string;
const char A = 'A', Z = 'Z';
- int startIndex = 0;
+ const char a = 'a', z = 'z';
+ int start_index = 0;
- for ( int i = 1; i < this->size()-1; i++ ) {
- bool isCapital = cstr[i] >= A && cstr[i] <= Z;
+ for ( size_t i = 1; i < this->size(); i++ ) {
+ bool is_upper = cstr[i] >= A && cstr[i] <= Z;
+ bool are_next_2_lower = false;
+ bool was_precedent_upper = cstr[i-1] >= A && cstr[i-1] <= Z;
- if ( isCapital ) {
- newString += "_" + this->substr(startIndex, i-startIndex);
- startIndex = i;
+ if (i+2 < this->size()) {
+ are_next_2_lower = cstr[i+1] >= a && cstr[i+1] <= z && cstr[i+2] >= a && cstr[i+2] <= z;
}
- }
- newString += "_" + this->substr(startIndex, this->size()-startIndex);
+ bool should_split = ((is_upper && !was_precedent_upper) || (was_precedent_upper && is_upper && are_next_2_lower));
+ if (should_split) {
+ new_string += this->substr(start_index, i - start_index) + "_";
+ start_index = i;
+ }
+ }
- return newString;
+ new_string += this->substr(start_index, this->size() - start_index);
+ return lowercase ? new_string.to_lower() : new_string;
}
+
+
int String::get_slice_count(String p_splitter) const{
if (empty())
diff --git a/core/ustring.h b/core/ustring.h
index 9276afa0f7..e65103ff99 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -149,7 +149,7 @@ public:
static double to_double(const CharType* p_str, const CharType **r_end=NULL);
static int64_t to_int(const CharType* p_str,int p_len=-1);
String capitalize() const;
- String camelcase_to_underscore() const;
+ String camelcase_to_underscore(bool lowercase=true) const;
int get_slice_count(String p_splitter) const;
String get_slice(String p_splitter,int p_slice) const;
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 3efa87de80..a3775156ac 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -338,6 +338,8 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri
exp_beg=true;
} else if ((c=='-' || c=='+') && !exp_sign && !exp_beg) {
+ if (c=='-')
+ is_float=true;
exp_sign=true;
} else {
@@ -358,6 +360,7 @@ Error VariantParser::get_token(Stream *p_stream, Token& r_token, int &line, Stri
r_token.type=TK_NUMBER;
+
if (is_float)
r_token.value=num.to_double();
else
@@ -542,7 +545,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
value=true;
else if (id=="false")
value=false;
- else if (id=="null")
+ else if (id=="null" || id=="nil")
value=Variant();
else if (id=="Vector2"){
@@ -1282,7 +1285,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
arr.resize(len);
DVector<Color>::Write w = arr.write();
for(int i=0;i<len;i++) {
- w[i]=Color(args[i*3+0],args[i*3+1],args[i*3+2],args[i*3+3]);
+ w[i]=Color(args[i*4+0],args[i*4+1],args[i*4+2],args[i*4+3]);
}
}
diff --git a/core/vector.h b/core/vector.h
index 641721f401..398d7f1bd5 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -68,11 +68,26 @@ class Vector {
return reinterpret_cast<T*>(_ptr);
}
-
- _FORCE_INLINE_ int _get_alloc_size(int p_elements) const {
-
- return nearest_power_of_2(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
- }
+
+ _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
+ return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
+ }
+
+ _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
+#if defined(_add_overflow) && defined(_mul_overflow)
+ size_t o;
+ size_t p;
+ if (_mul_overflow(p_elements, sizeof(T), &o)) return false;
+ if (_add_overflow(o, sizeof(SafeRefCount)+sizeof(int), &p)) return false;
+ *out = nearest_power_of_2_templated(p);
+ return true;
+#else
+ // Speed is more important than correctness here, do the operations unchecked
+ // and hope the best
+ *out = _get_alloc_size(p_elements);
+ return true;
+#endif
+ }
void _unref(void *p_data);
@@ -257,19 +272,21 @@ Error Vector<T>::resize(int p_size) {
// possibly changing size, copy on write
_copy_on_write();
+ size_t alloc_size;
+ ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY);
+
if (p_size>size()) {
if (size()==0) {
// alloc from scratch
- void* ptr=memalloc(_get_alloc_size(p_size));
+ void* ptr=memalloc(alloc_size);
ERR_FAIL_COND_V( !ptr ,ERR_OUT_OF_MEMORY);
_ptr=(T*)((uint8_t*)ptr+sizeof(int)+sizeof(SafeRefCount));
_get_refcount()->init(); // init refcount
*_get_size()=0; // init size (currently, none)
} else {
-
- void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size));
+ void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
_ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
}
@@ -293,7 +310,7 @@ Error Vector<T>::resize(int p_size) {
t->~T();
}
- void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount),_get_alloc_size(p_size));
+ void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
_ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
diff --git a/demos/2d/platformer/stage.xml b/demos/2d/platformer/stage.xml
index 3b5d281551..ea0daf3ff8 100644
--- a/demos/2d/platformer/stage.xml
+++ b/demos/2d/platformer/stage.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="10" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
- <ext_resource path="res://tileset.xml" type="TileSet" index="0"></ext_resource>
+<resource_file type="PackedScene" subresource_count="10" version="2.0" version_name="Godot Engine v2.0.beta.custom_build">
<ext_resource path="res://music.ogg" type="AudioStream" index="6"></ext_resource>
+ <ext_resource path="res://tileset.xml" type="TileSet" index="0"></ext_resource>
<ext_resource path="res://coin.xml" type="PackedScene" index="1"></ext_resource>
- <ext_resource path="res://one_way_platform.xml" type="PackedScene" index="4"></ext_resource>
<ext_resource path="res://moving_platform.xml" type="PackedScene" index="2"></ext_resource>
- <ext_resource path="res://enemy.xml" type="PackedScene" index="7"></ext_resource>
- <ext_resource path="res://seesaw.xml" type="PackedScene" index="3"></ext_resource>
+ <ext_resource path="res://one_way_platform.xml" type="PackedScene" index="4"></ext_resource>
<ext_resource path="res://player.xml" type="PackedScene" index="5"></ext_resource>
+ <ext_resource path="res://seesaw.xml" type="PackedScene" index="3"></ext_resource>
+ <ext_resource path="res://enemy.xml" type="PackedScene" index="7"></ext_resource>
<ext_resource path="res://parallax_bg.xml" type="PackedScene" index="8"></ext_resource>
<main_resource>
<dictionary name="_bundled" shared="false">
@@ -19,7 +19,7 @@
<array len="0" shared="false">
</array>
<string> "names" </string>
- <string_array len="112">
+ <string_array len="110">
<string> "stage" </string>
<string> "__meta__" </string>
<string> "Node" </string>
@@ -37,14 +37,13 @@
<string> "collision/bounce" </string>
<string> "collision/layers" </string>
<string> "collision/mask" </string>
+ <string> "occluder/light_mask" </string>
<string> "tile_data" </string>
<string> "TileMap" </string>
<string> "coins" </string>
<string> "coin" </string>
<string> "transform/pos" </string>
- <string> "input/pickable" </string>
<string> "linear_damp" </string>
- <string> "angular_damp" </string>
<string> "coin 2" </string>
<string> "coin 3" </string>
<string> "coin 4" </string>
@@ -118,7 +117,6 @@
<string> "enemy 14" </string>
<string> "enemy 15" </string>
<string> "parallax_bg" </string>
- <string> "scroll/ignore_camera_zoom" </string>
<string> "Label" </string>
<string> "margin/left" </string>
<string> "margin/top" </string>
@@ -139,144 +137,12 @@
<array len="0" shared="false">
</array>
<string> "nodes" </string>
- <int_array len="925"> -1, -1, 2, 0, -1, 1, 1, 0, 0, 0, 0, 18, 3, -1, 15, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 1, 11, 7, 12, 7, 13, 8, 14, 9, 15, 10, 16, 10, 17, 11, 1, 12, 0, 0, 0, 2, 19, -1, 0, 0, 2, 0, 2147483647, 20, 13, 4, 21, 14, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 25, 13, 4, 21, 17, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 26, 13, 4, 21, 18, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 27, 13, 4, 21, 19, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 28, 13, 4, 21, 20, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 29, 13, 4, 21, 21, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 30, 13, 4, 21, 22, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 31, 13, 4, 21, 23, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 32, 13, 4, 21, 24, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 33, 13, 4, 21, 25, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 34, 13, 4, 21, 26, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 35, 13, 4, 21, 27, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 36, 13, 4, 21, 28, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 37, 13, 4, 21, 29, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 38, 13, 4, 21, 30, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 39, 13, 4, 21, 31, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 40, 13, 4, 21, 32, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 41, 13, 4, 21, 33, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 42, 13, 4, 21, 34, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 43, 13, 4, 21, 35, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 44, 13, 4, 21, 36, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 45, 13, 4, 21, 37, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 46, 13, 4, 21, 38, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 47, 13, 4, 21, 39, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 48, 13, 4, 21, 40, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 49, 13, 4, 21, 41, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 50, 13, 4, 21, 42, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 51, 13, 4, 21, 43, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 52, 13, 4, 21, 44, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 53, 13, 4, 21, 45, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 54, 13, 4, 21, 46, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 55, 13, 4, 21, 47, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 56, 13, 4, 21, 48, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 57, 13, 4, 21, 49, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 58, 13, 4, 21, 50, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 59, 13, 4, 21, 51, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 60, 13, 4, 21, 52, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 61, 13, 4, 21, 53, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 62, 13, 4, 21, 54, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 63, 13, 4, 21, 55, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 64, 13, 4, 21, 56, 22, 15, 23, 16, 24, 8, 0, 2, 0, 2147483647, 65, 13, 4, 21, 57, 22, 15, 23, 16, 24, 8, 0, 0, 0, 2, 66, -1, 0, 0, 45, 0, 2147483647, 67, 58, 3, 21, 59, 68, 60, 69, 61, 0, 45, 0, 2147483647, 70, 58, 3, 21, 62, 68, 63, 69, 64, 0, 45, 0, 2147483647, 71, 58, 3, 21, 65, 68, 66, 69, 64, 0, 45, 0, 2147483647, 72, 67, 1, 21, 68, 0, 45, 0, 2147483647, 73, 69, 1, 21, 70, 0, 0, 0, 2147483647, 74, 71, 1, 21, 72, 0, 0, 0, 84, 75, -1, 8, 76, 73, 77, 7, 78, 15, 79, 74, 80, 15, 81, 7, 82, 9, 83, 75, 0, 0, 0, 2, 85, -1, 0, 0, 53, 0, 2147483647, 86, 76, 1, 21, 77, 0, 53, 0, 2147483647, 87, 76, 1, 21, 78, 0, 53, 0, 2147483647, 88, 76, 1, 21, 79, 0, 53, 0, 2147483647, 89, 76, 1, 21, 80, 0, 53, 0, 2147483647, 90, 76, 1, 21, 81, 0, 53, 0, 2147483647, 91, 76, 1, 21, 82, 0, 53, 0, 2147483647, 92, 76, 1, 21, 83, 0, 53, 0, 2147483647, 93, 76, 1, 21, 84, 0, 53, 0, 2147483647, 94, 76, 1, 21, 85, 0, 53, 0, 2147483647, 95, 76, 1, 21, 86, 0, 53, 0, 2147483647, 96, 76, 1, 21, 87, 0, 0, 0, 2147483647, 97, 88, 1, 98, 7, 0, 0, 0, 99, 99, -1, 12, 100, 89, 101, 90, 102, 91, 103, 92, 104, 15, 105, 15, 106, 6, 107, 93, 108, 15, 109, 8, 110, 1, 111, 94, 0 </int_array>
+ <int_array len="757"> -1, -1, 2, 0, -1, 1, 1, 0, 0, 0, 0, 19, 3, -1, 16, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 1, 11, 7, 12, 7, 13, 8, 14, 9, 15, 10, 16, 10, 17, 10, 18, 11, 1, 12, 0, 0, 0, 2, 20, -1, 0, 0, 2, 0, 2147483647, 21, 13, 2, 22, 14, 23, 15, 0, 2, 0, 2147483647, 24, 13, 2, 22, 16, 23, 15, 0, 2, 0, 2147483647, 25, 13, 2, 22, 17, 23, 15, 0, 2, 0, 2147483647, 26, 13, 2, 22, 18, 23, 15, 0, 2, 0, 2147483647, 27, 13, 2, 22, 19, 23, 15, 0, 2, 0, 2147483647, 28, 13, 2, 22, 20, 23, 15, 0, 2, 0, 2147483647, 29, 13, 2, 22, 21, 23, 15, 0, 2, 0, 2147483647, 30, 13, 2, 22, 22, 23, 15, 0, 2, 0, 2147483647, 31, 13, 2, 22, 23, 23, 15, 0, 2, 0, 2147483647, 32, 13, 2, 22, 24, 23, 15, 0, 2, 0, 2147483647, 33, 13, 2, 22, 25, 23, 15, 0, 2, 0, 2147483647, 34, 13, 2, 22, 26, 23, 15, 0, 2, 0, 2147483647, 35, 13, 2, 22, 27, 23, 15, 0, 2, 0, 2147483647, 36, 13, 2, 22, 28, 23, 15, 0, 2, 0, 2147483647, 37, 13, 2, 22, 29, 23, 15, 0, 2, 0, 2147483647, 38, 13, 2, 22, 30, 23, 15, 0, 2, 0, 2147483647, 39, 13, 2, 22, 31, 23, 15, 0, 2, 0, 2147483647, 40, 13, 2, 22, 32, 23, 15, 0, 2, 0, 2147483647, 41, 13, 2, 22, 33, 23, 15, 0, 2, 0, 2147483647, 42, 13, 2, 22, 34, 23, 15, 0, 2, 0, 2147483647, 43, 13, 2, 22, 35, 23, 15, 0, 2, 0, 2147483647, 44, 13, 2, 22, 36, 23, 15, 0, 2, 0, 2147483647, 45, 13, 2, 22, 37, 23, 15, 0, 2, 0, 2147483647, 46, 13, 2, 22, 38, 23, 15, 0, 2, 0, 2147483647, 47, 13, 2, 22, 39, 23, 15, 0, 2, 0, 2147483647, 48, 13, 2, 22, 40, 23, 15, 0, 2, 0, 2147483647, 49, 13, 2, 22, 41, 23, 15, 0, 2, 0, 2147483647, 50, 13, 2, 22, 42, 23, 15, 0, 2, 0, 2147483647, 51, 13, 2, 22, 43, 23, 15, 0, 2, 0, 2147483647, 52, 13, 2, 22, 44, 23, 15, 0, 2, 0, 2147483647, 53, 13, 2, 22, 45, 23, 15, 0, 2, 0, 2147483647, 54, 13, 2, 22, 46, 23, 15, 0, 2, 0, 2147483647, 55, 13, 2, 22, 47, 23, 15, 0, 2, 0, 2147483647, 56, 13, 2, 22, 48, 23, 15, 0, 2, 0, 2147483647, 57, 13, 2, 22, 49, 23, 15, 0, 2, 0, 2147483647, 58, 13, 2, 22, 50, 23, 15, 0, 2, 0, 2147483647, 59, 13, 2, 22, 51, 23, 15, 0, 2, 0, 2147483647, 60, 13, 2, 22, 52, 23, 15, 0, 2, 0, 2147483647, 61, 13, 2, 22, 53, 23, 15, 0, 2, 0, 2147483647, 62, 13, 2, 22, 54, 23, 15, 0, 2, 0, 2147483647, 63, 13, 2, 22, 55, 23, 15, 0, 2, 0, 2147483647, 64, 13, 2, 22, 56, 23, 15, 0, 0, 0, 2, 65, -1, 0, 0, 45, 0, 2147483647, 66, 57, 3, 22, 58, 67, 59, 68, 60, 0, 45, 0, 2147483647, 69, 57, 3, 22, 61, 67, 62, 68, 63, 0, 45, 0, 2147483647, 70, 57, 3, 22, 64, 67, 65, 68, 63, 0, 45, 0, 2147483647, 71, 66, 1, 22, 67, 0, 45, 0, 2147483647, 72, 68, 1, 22, 69, 0, 0, 0, 2147483647, 73, 70, 1, 22, 71, 0, 0, 0, 83, 74, -1, 8, 75, 72, 76, 7, 77, 73, 78, 74, 79, 73, 80, 7, 81, 9, 82, 75, 0, 0, 0, 2, 84, -1, 0, 0, 53, 0, 2147483647, 85, 76, 1, 22, 77, 0, 53, 0, 2147483647, 86, 76, 1, 22, 78, 0, 53, 0, 2147483647, 87, 76, 1, 22, 79, 0, 53, 0, 2147483647, 88, 76, 1, 22, 80, 0, 53, 0, 2147483647, 89, 76, 1, 22, 81, 0, 53, 0, 2147483647, 90, 76, 1, 22, 82, 0, 53, 0, 2147483647, 91, 76, 1, 22, 83, 0, 53, 0, 2147483647, 92, 76, 1, 22, 84, 0, 53, 0, 2147483647, 93, 76, 1, 22, 85, 0, 53, 0, 2147483647, 94, 76, 1, 22, 86, 0, 53, 0, 2147483647, 95, 76, 1, 22, 87, 0, 0, 0, 2147483647, 96, 88, 0, 0, 0, 0, 97, 97, -1, 12, 98, 89, 99, 90, 100, 91, 101, 92, 102, 73, 103, 73, 104, 6, 105, 93, 106, 73, 107, 8, 108, 1, 109, 94, 0 </int_array>
<string> "variants" </string>
<array len="95" shared="false">
<dictionary shared="false">
<string> "__editor_plugin_screen__" </string>
- <string> "Script" </string>
- <string> "__editor_plugin_states__" </string>
- <dictionary shared="false">
- <string> "2D" </string>
- <dictionary shared="false">
- <string> "ofs" </string>
- <vector2> -70.6559, 735.599 </vector2>
- <string> "snap_grid" </string>
- <bool> False </bool>
- <string> "snap_offset" </string>
- <vector2> 0, 0 </vector2>
- <string> "snap_pixel" </string>
- <bool> False </bool>
- <string> "snap_relative" </string>
- <bool> False </bool>
- <string> "snap_rotation" </string>
- <bool> False </bool>
- <string> "snap_rotation_offset" </string>
- <real> 0 </real>
- <string> "snap_rotation_step" </string>
- <real> 0.261799 </real>
- <string> "snap_show_grid" </string>
- <bool> False </bool>
- <string> "snap_step" </string>
- <vector2> 10, 10 </vector2>
- <string> "zoom" </string>
- <real> 0.663419 </real>
- </dictionary>
- <string> "3D" </string>
- <dictionary shared="false">
- <string> "ambient_light_color" </string>
- <color> 0.15, 0.15, 0.15, 1 </color>
- <string> "default_light" </string>
- <bool> True </bool>
- <string> "default_srgb" </string>
- <bool> False </bool>
- <string> "deflight_rot_x" </string>
- <real> 0.942478 </real>
- <string> "deflight_rot_y" </string>
- <real> 0.628319 </real>
- <string> "fov" </string>
- <real> 45 </real>
- <string> "show_grid" </string>
- <bool> True </bool>
- <string> "show_origin" </string>
- <bool> True </bool>
- <string> "viewport_mode" </string>
- <int> 1 </int>
- <string> "viewports" </string>
- <array len="4" shared="false">
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 18.643827 </real>
- <string> "listener" </string>
- <bool> True </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- <dictionary shared="false">
- <string> "distance" </string>
- <real> 4 </real>
- <string> "listener" </string>
- <bool> False </bool>
- <string> "pos" </string>
- <vector3> 0, 0, 0 </vector3>
- <string> "use_environment" </string>
- <bool> False </bool>
- <string> "use_orthogonal" </string>
- <bool> False </bool>
- <string> "x_rot" </string>
- <real> 0 </real>
- <string> "y_rot" </string>
- <real> 0 </real>
- </dictionary>
- </array>
- <string> "zfar" </string>
- <real> 500 </real>
- <string> "znear" </string>
- <real> 0.1 </real>
- </dictionary>
- <string> "Anim" </string>
- <dictionary shared="false">
- <string> "visible" </string>
- <bool> False </bool>
- </dictionary>
- </dictionary>
- <string> "__editor_run_settings__" </string>
- <dictionary shared="false">
- <string> "custom_args" </string>
- <string> "-l $scene" </string>
- <string> "run_mode" </string>
- <int> 0 </int>
- </dictionary>
+ <string> "2D" </string>
</dictionary>
<int> 0 </int>
<resource external="0"> </resource>
@@ -288,14 +154,13 @@
<real> 1 </real>
<real> 0 </real>
<int> 1 </int>
- <int_array len="2008"> 0, 2, 70, 536870914, 71, 10, 72, 10, 73, 10, 74, 10, 75, 10, 76, 10, 77, 10, 78, 10, 65536, 2, 65606, 536870914, 65607, 10, 65608, 10, 65609, 10, 65610, 10, 65611, 10, 65612, 10, 65613, 10, 65614, 10, 131072, 2, 131142, 536870914, 131143, 10, 131144, 10, 131145, 10, 131146, 10, 131147, 10, 131148, 10, 131149, 10, 131150, 10, 196608, 2, 196626, 9, 196678, 536870914, 196679, 10, 196680, 10, 196681, 10, 196682, 10, 196683, 10, 196684, 10, 196685, 10, 196686, 10, 262144, 2, 262162, 8, 262214, 536870914, 262215, 10, 262216, 10, 262217, 10, 262218, 10, 262219, 10, 262220, 10, 262221, 10, 262222, 10, 327680, 2, 327697, 536870921, 327698, 7, 327733, 9, 327750, 536870914, 327751, 10, 327752, 10, 327753, 10, 327754, 10, 327755, 10, 327756, 10, 327757, 10, 327758, 10, 393216, 2, 393233, 536870920, 393234, 7, 393257, 9, 393269, 7, 393286, 536870914, 393287, 10, 393288, 10, 393289, 10, 393290, 10, 393291, 10, 393292, 10, 393293, 10, 393294, 10, 458752, 2, 458769, 7, 458770, 8, 458790, 9, 458793, 8, 458805, 8, 458822, 536870914, 458823, 10, 458824, 10, 458825, 10, 458826, 10, 458827, 10, 458828, 10, 458829, 10, 458830, 10, 524288, 4, 524289, 1, 524304, 536870913, 524305, 536870918, 524306, 6, 524307, 5, 524308, 1, 524326, 8, 524329, 7, 524341, 7, 524358, 536870914, 524359, 10, 524360, 10, 524361, 10, 524362, 10, 524363, 10, 524364, 10, 524365, 10, 524366, 10, 589824, 10, 589825, 13, 589840, 536870914, 589841, 10, 589842, 10, 589843, 10, 589844, 2, 589862, 7, 589865, 7, 589876, 536870913, 589877, 6, 589878, 1, 589894, 536870914, 589895, 10, 589896, 10, 589897, 10, 589898, 10, 589899, 10, 589900, 10, 589901, 10, 589902, 10, 655360, 2, 655376, 536870914, 655377, 10, 655378, 10, 655379, 10, 655380, 2, 655398, 7, 655401, 8, 655412, 536870925, 655413, 11, 655414, 13, 655430, 536870914, 655431, 10, 655432, 10, 655433, 10, 655434, 10, 655435, 10, 655436, 10, 655437, 10, 655438, 10, 720896, 2, 720912, 536870914, 720913, 10, 720914, 10, 720915, 10, 720916, 2, 720934, 8, 720937, 7, 720958, 536870913, 720959, 5, 720960, 536870917, 720961, 5, 720962, 5, 720963, 536870917, 720964, 5, 720965, 0, 720966, 536870916, 720967, 10, 720968, 10, 720969, 10, 720970, 10, 720971, 10, 720972, 10, 720973, 10, 720974, 10, 786432, 2, 786437, 9, 786448, 536870914, 786449, 10, 786450, 10, 786451, 10, 786452, 2, 786464, 536870913, 786465, 1, 786470, 7, 786473, 7, 786474, 536870924, 786475, 1, 786494, 536870914, 786495, 10, 786496, 10, 786497, 10, 786498, 10, 786499, 10, 786500, 10, 786501, 10, 786502, 10, 786503, 10, 786504, 10, 786505, 10, 786506, 10, 786507, 10, 786508, 10, 786509, 10, 851968, 2, 851973, 7, 851984, 536870914, 851985, 10, 851986, 10, 851987, 10, 851988, 2, 851996, 536870913, 851997, 1, 852000, 536870914, 852001, 3, 852006, 7, 852009, 536870913, 852011, 2, 852030, 536870914, 852031, 10, 852032, 10, 852033, 10, 852034, 10, 852035, 10, 852036, 10, 852037, 10, 852038, 10, 852039, 10, 852040, 10, 852041, 10, 852042, 10, 852043, 10, 852044, 10, 852045, 10, 917504, 2, 917506, 9, 917509, 7, 917512, 536870921, 917520, 536870925, 917521, 11, 917522, 11, 917523, 11, 917524, 13, 917532, 536870925, 917533, 13, 917536, 536870914, 917537, 4, 917538, 1, 917540, 536870913, 917541, 0, 917542, 1, 917545, 536870914, 917546, 10, 917547, 4, 917548, 1, 917566, 536870914, 917567, 10, 917568, 10, 917569, 10, 917570, 10, 917571, 10, 917572, 10, 917573, 10, 917574, 10, 917575, 10, 917576, 10, 917577, 10, 917578, 10, 917579, 10, 917580, 10, 917581, 10, 983040, 2, 983042, 7, 983045, 7, 983048, 536870920, 983050, 536870913, 983051, 0, 983052, 1, 983064, 536870913, 983065, 1, 983072, 536870914, 983073, 10, 983074, 4, 983075, 0, 983076, 536870916, 983077, 10, 983078, 4, 983079, 536870912, 983080, 536870912, 983081, 536870916, 983082, 10, 983083, 10, 983084, 2, 983095, 9, 983102, 536870914, 983103, 10, 983104, 10, 983105, 10, 983106, 10, 983107, 10, 983108, 10, 983109, 10, 983110, 10, 983111, 10, 983112, 10, 983113, 10, 983114, 10, 983115, 10, 983116, 10, 983117, 10, 1048576, 2, 1048578, 8, 1048581, 8, 1048584, 536870919, 1048586, 536870914, 1048587, 536870922, 1048588, 2, 1048600, 536870925, 1048601, 13, 1048604, 9, 1048608, 536870925, 1048609, 536870923, 1048610, 536870923, 1048611, 536870923, 1048612, 10, 1048613, 10, 1048614, 10, 1048615, 10, 1048616, 10, 1048617, 10, 1048618, 10, 1048619, 10, 1048620, 4, 1048621, 1, 1048630, 536870921, 1048631, 8, 1048638, 536870914, 1048639, 10, 1048640, 10, 1048641, 10, 1048642, 10, 1048643, 10, 1048644, 10, 1048645, 10, 1048646, 10, 1048647, 10, 1048648, 10, 1048649, 10, 1048650, 10, 1048651, 10, 1048652, 10, 1048653, 10, 1114112, 4, 1114113, 0, 1114114, 6, 1114115, 0, 1114116, 0, 1114117, 6, 1114118, 1, 1114120, 536870920, 1114122, 536870925, 1114123, 11, 1114124, 13, 1114128, 536870913, 1114129, 5, 1114130, 536870917, 1114131, 5, 1114132, 0, 1114133, 1, 1114140, 7, 1114141, 536870921, 1114148, 536870914, 1114149, 10, 1114150, 10, 1114151, 10, 1114152, 10, 1114153, 10, 1114154, 10, 1114155, 10, 1114156, 10, 1114157, 2, 1114166, 536870920, 1114167, 8, 1114174, 536870914, 1114175, 10, 1114176, 10, 1114177, 10, 1114178, 10, 1114179, 10, 1114180, 10, 1114181, 10, 1114182, 10, 1114183, 10, 1114184, 10, 1114185, 10, 1114186, 10, 1114187, 10, 1114188, 10, 1179648, 10, 1179649, 10, 1179650, 10, 1179651, 10, 1179652, 10, 1179653, 10, 1179654, 2, 1179656, 536870919, 1179663, 536870915, 1179665, 10, 1179666, 10, 1179667, 10, 1179668, 10, 1179669, 4, 1179670, 12, 1179675, 9, 1179676, 8, 1179677, 8, 1179684, 536870914, 1179685, 10, 1179686, 10, 1179687, 10, 1179688, 10, 1179689, 10, 1179690, 10, 1179691, 10, 1179692, 10, 1179693, 4, 1179694, 1, 1179701, 9, 1179702, 536870919, 1179703, 7, 1179710, 536870914, 1179711, 10, 1179712, 10, 1179713, 10, 1179714, 10, 1179715, 10, 1179716, 10, 1179717, 10, 1179718, 10, 1179719, 10, 1179720, 10, 1179721, 10, 1179722, 10, 1245184, 10, 1245185, 10, 1245186, 10, 1245187, 10, 1245188, 10, 1245189, 10, 1245190, 2, 1245192, 536870919, 1245199, 536870913, 1245200, 536870916, 1245201, 10, 1245202, 10, 1245203, 10, 1245204, 10, 1245205, 10, 1245207, 1, 1245211, 7, 1245212, 7, 1245213, 536870920, 1245220, 536870914, 1245221, 10, 1245222, 10, 1245223, 10, 1245224, 10, 1245225, 10, 1245226, 10, 1245227, 10, 1245228, 10, 1245229, 10, 1245230, 2, 1245237, 8, 1245238, 536870919, 1245239, 8, 1245240, 536870921, 1245246, 536870914, 1245247, 10, 1245248, 10, 1245249, 10, 1245250, 10, 1245251, 10, 1245252, 10, 1245253, 10, 1245254, 10, 1245255, 10, 1245256, 10, 1245257, 10, 1245258, 10, 1310720, 10, 1310721, 10, 1310722, 10, 1310723, 10, 1310724, 10, 1310725, 10, 1310726, 2, 1310728, 536870920, 1310730, 536870913, 1310731, 1, 1310734, 536870913, 1310735, 536870916, 1310736, 10, 1310737, 10, 1310738, 10, 1310739, 10, 1310740, 10, 1310741, 10, 1310742, 10, 1310743, 4, 1310744, 1, 1310747, 8, 1310748, 7, 1310749, 536870919, 1310756, 536870914, 1310757, 10, 1310758, 10, 1310759, 10, 1310760, 10, 1310761, 10, 1310762, 10, 1310763, 10, 1310764, 10, 1310765, 10, 1310766, 4, 1310767, 5, 1310768, 12, 1310773, 7, 1310774, 536870919, 1310775, 7, 1310776, 536870919, 1310782, 536870914, 1310783, 10, 1310784, 10, 1310785, 10, 1310786, 10, 1310787, 10, 1310788, 10, 1310789, 10, 1310790, 10, 1310791, 10, 1310792, 10, 1310793, 10, 1376256, 10, 1376257, 10, 1376258, 10, 1376259, 10, 1376260, 10, 1376261, 10, 1376262, 4, 1376263, 0, 1376264, 0, 1376265, 0, 1376266, 536870916, 1376267, 4, 1376268, 0, 1376269, 0, 1376270, 536870916, 1376271, 10, 1376272, 10, 1376273, 10, 1376274, 10, 1376275, 10, 1376276, 10, 1376277, 10, 1376278, 10, 1376279, 10, 1376280, 4, 1376281, 12, 1376283, 8, 1376284, 8, 1376285, 536870920, 1376287, 536870924, 1376288, 0, 1376289, 5, 1376290, 536870917, 1376291, 0, 1376292, 536870916, 1376293, 10, 1376294, 10, 1376295, 10, 1376296, 10, 1376297, 10, 1376298, 10, 1376299, 10, 1376300, 10, 1376301, 10, 1376302, 10, 1376303, 10, 1376305, 12, 1376309, 7, 1376310, 536870920, 1376311, 7, 1376312, 536870920, 1376318, 536870914, 1376319, 10, 1376320, 10, 1376321, 10, 1376322, 10, 1376323, 10, 1376324, 10, 1376325, 10, 1376326, 10, 1376327, 10, 1376328, 10, 1441792, 10, 1441793, 10, 1441794, 10, 1441795, 10, 1441796, 10, 1441797, 10, 1441798, 10, 1441799, 10, 1441800, 10, 1441801, 10, 1441802, 10, 1441803, 10, 1441804, 10, 1441805, 10, 1441806, 10, 1441807, 10, 1441808, 10, 1441809, 10, 1441810, 10, 1441811, 10, 1441812, 10, 1441813, 10, 1441814, 10, 1441815, 10, 1441816, 10, 1441818, 0, 1441819, 6, 1441820, 6, 1441821, 536870918, 1441822, 5, 1441824, 10, 1441825, 10, 1441826, 10, 1441827, 10, 1441828, 10, 1441829, 10, 1441830, 10, 1441831, 10, 1441832, 10, 1441833, 10, 1441834, 10, 1441835, 10, 1441836, 10, 1441837, 10, 1441838, 10, 1441839, 10, 1441840, 10, 1441842, 0, 1441843, 0, 1441844, 0, 1441845, 6, 1441846, 536870918, 1441847, 6, 1441848, 536870918, 1441849, 0, 1441850, 5, 1441851, 536870917, 1441852, 5, 1441853, 0, 1441854, 536870916, 1441855, 10, 1441856, 10, 1441857, 10, 1441858, 10, 1441859, 10, 1441860, 10, 1441861, 10, 1441862, 10, 1441863, 10, 1507328, 10, 1507329, 10, 1507330, 10, 1507331, 10, 1507332, 10, 1507333, 10, 1507334, 10, 1507335, 10, 1507336, 10, 1507337, 10, 1507338, 10, 1507339, 10, 1507340, 10, 1507341, 10, 1507342, 10, 1507343, 10, 1507344, 10, 1507345, 10, 1507346, 10, 1507347, 10, 1507348, 10, 1507349, 10, 1507350, 10, 1507351, 10, 1507352, 10, 1507353, 10, 1507354, 10, 1507355, 10, 1507356, 10, 1507357, 10, 1507358, 10, 1507359, 10, 1507360, 10, 1507361, 10, 1507362, 10, 1507363, 10, 1507364, 10, 1507365, 10, 1507366, 10, 1507367, 10, 1507368, 10, 1507369, 10, 1507370, 10, 1507371, 10, 1507372, 10, 1507373, 10, 1507374, 10, 1507375, 10, 1507376, 10, 1507377, 10, 1507378, 10, 1507379, 10, 1507380, 10, 1507381, 10, 1507382, 10, 1507383, 10, 1507384, 10, 1507385, 10, 1507386, 10, 1507387, 10, 1507388, 10, 1507389, 10, 1507390, 10, 1507391, 10, 1507392, 10, 1507393, 10, 1507394, 10, 1507395, 10, 1507396, 10, 1507397, 10, 1507398, 10, 1507399, 10, 1572864, 10, 1572865, 10, 1572866, 10, 1572867, 10, 1572868, 10, 1572869, 10, 1572870, 10, 1572871, 10, 1572872, 10, 1572873, 10, 1572874, 10, 1572875, 10, 1572876, 10, 1572877, 10, 1572878, 10, 1572879, 10, 1572880, 10, 1572881, 10, 1572882, 10, 1572883, 10, 1572884, 10, 1572885, 10, 1572886, 10, 1572887, 10, 1572888, 10, 1572889, 10, 1572890, 10, 1572891, 10, 1572892, 10, 1572893, 10, 1572894, 10, 1572895, 10, 1572896, 10, 1572897, 10, 1572898, 10, 1572899, 10, 1572900, 10, 1572901, 10, 1572902, 10, 1572903, 10, 1572904, 10, 1572905, 10, 1572906, 10, 1572907, 10, 1572908, 10, 1572909, 10, 1572910, 10, 1572911, 10, 1572912, 10, 1572913, 10, 1572914, 10, 1572915, 10, 1572916, 10, 1572917, 10, 1572918, 10, 1572919, 10, 1572920, 10, 1572921, 10, 1572922, 10, 1572923, 10, 1572924, 10, 1572925, 10, 1572926, 10, 1572927, 10, 1572928, 10, 1572929, 10, 1572930, 10, 1572931, 10, 1572932, 10, 1572933, 10, 1572934, 10, 1572935, 10, 1638400, 10, 1638401, 10, 1638402, 10, 1638403, 10, 1638404, 10, 1638405, 10, 1638406, 10, 1638407, 10, 1638408, 10, 1638409, 10, 1638410, 10, 1638411, 10, 1638412, 10, 1638413, 10, 1638414, 10, 1638415, 10, 1638416, 10, 1638417, 10, 1638418, 10, 1638419, 10, 1638420, 10, 1638421, 10, 1638422, 10, 1638423, 10, 1638424, 10, 1638425, 10, 1638426, 10, 1638427, 10, 1638428, 10, 1638429, 10, 1638430, 10, 1638431, 10, 1638432, 10, 1638433, 10, 1638434, 10, 1638435, 10, 1638436, 10, 1638437, 10, 1638438, 10, 1638439, 10, 1638440, 10, 1638441, 10, 1638442, 10, 1638443, 10, 1638444, 10, 1638445, 10, 1638446, 10, 1638447, 10, 1638448, 10, 1638449, 10, 1638450, 10, 1638451, 10, 1638452, 10, 1638453, 10, 1638454, 10, 1638455, 10, 1638456, 10, 1638457, 10, 1638458, 10, 1638459, 10, 1638460, 10, 1638461, 10, 1638462, 10, 1638463, 10, 1638464, 10, 1638465, 10, 1638466, 10, 1638467, 10, 1638468, 10, 1638469, 10, 1638470, 10, 1638471, 10, 1703952, 10, 1703953, 10, 1703954, 10, 1703955, 10, 1703956, 10, 1703957, 10, 1703958, 10, 1703959, 10, 1703960, 10, 1703961, 10, 1703962, 10, 1703963, 10, 1703964, 10, 1703965, 10, 1703966, 10, 1703967, 10, 1703968, 10, 1703969, 10, 1703970, 10, 1703971, 10, 1703972, 10, 1703973, 10, 1703974, 10, 1703975, 10, 1703976, 10, 1703977, 10, 1703978, 10, 1703979, 10, 1703980, 10, 1703981, 10, 1703982, 10, 1703983, 10, 1703984, 10, 1703985, 10, 1703986, 10, 1703987, 10, 1703988, 10, 1703989, 10, 1703990, 10, 1703991, 10, 1703992, 10, 1703993, 10, 1703994, 10, 1703995, 10, 1703996, 10, 1703997, 10, 1703998, 10, 1703999, 10, 1704000, 10, 1704001, 10, 1704002, 10, 1704003, 10, 1704004, 10, 1704005, 10, 1704006, 10, 1704007, 10, 1769488, 10, 1769489, 10, 1769490, 10, 1769491, 10, 1769492, 10, 1769493, 10, 1769494, 10, 1769495, 10, 1769496, 10, 1769497, 10, 1769498, 10, 1769499, 10, 1769500, 10, 1769501, 10, 1769502, 10, 1769503, 10, 1769504, 10, 1769505, 10, 1769506, 10, 1769507, 10, 1769508, 10, 1769509, 10, 1769510, 10, 1769511, 10, 1769512, 10, 1769513, 10, 1769514, 10, 1769515, 10, 1769516, 10, 1769517, 10, 1769518, 10, 1769519, 10, 1769520, 10, 1769521, 10, 1769522, 10, 1769523, 10, 1769524, 10, 1769525, 10, 1769526, 10, 1769527, 10, 1769528, 10, 1769529, 10, 1769530, 10, 1769531, 10, 1769532, 10, 1769533, 10, 1769534, 10, 1769535, 10, 1769536, 10, 1769537, 10, 1769538, 10, 1769539, 10, 1769540, 10, 1769541, 10 </int_array>
+ <int_array len="2008"> 0, 2, 70, 536870914, 71, 10, 72, 10, 73, 10, 74, 10, 75, 10, 76, 10, 77, 10, 78, 10, 65536, 2, 65606, 536870914, 65607, 10, 65608, 10, 65609, 10, 65610, 10, 65611, 10, 65612, 10, 65613, 10, 65614, 10, 131072, 2, 131142, 536870914, 131143, 10, 131144, 10, 131145, 10, 131146, 10, 131147, 10, 131148, 10, 131149, 10, 131150, 10, 196608, 2, 196626, 9, 196678, 536870914, 196679, 10, 196680, 10, 196681, 10, 196682, 10, 196683, 10, 196684, 10, 196685, 10, 196686, 10, 262144, 2, 262162, 8, 262214, 536870914, 262215, 10, 262216, 10, 262217, 10, 262218, 10, 262219, 10, 262220, 10, 262221, 10, 262222, 10, 327680, 2, 327697, 536870921, 327698, 7, 327733, 9, 327750, 536870914, 327751, 10, 327752, 10, 327753, 10, 327754, 10, 327755, 10, 327756, 10, 327757, 10, 327758, 10, 393216, 2, 393233, 536870920, 393234, 7, 393257, 9, 393269, 7, 393286, 536870914, 393287, 10, 393288, 10, 393289, 10, 393290, 10, 393291, 10, 393292, 10, 393293, 10, 393294, 10, 458752, 2, 458769, 7, 458770, 8, 458790, 9, 458793, 8, 458805, 8, 458822, 536870914, 458823, 10, 458824, 10, 458825, 10, 458826, 10, 458827, 10, 458828, 10, 458829, 10, 458830, 10, 524288, 4, 524289, 1, 524304, 536870913, 524305, 536870918, 524306, 6, 524307, 5, 524308, 1, 524326, 8, 524329, 7, 524341, 7, 524358, 536870914, 524359, 10, 524360, 10, 524361, 10, 524362, 10, 524363, 10, 524364, 10, 524365, 10, 524366, 10, 589824, 10, 589825, 13, 589840, 536870914, 589841, 10, 589842, 10, 589843, 10, 589844, 2, 589862, 7, 589865, 7, 589876, 536870913, 589877, 6, 589878, 1, 589894, 536870914, 589895, 10, 589896, 10, 589897, 10, 589898, 10, 589899, 10, 589900, 10, 589901, 10, 589902, 10, 655360, 2, 655376, 536870914, 655377, 10, 655378, 10, 655379, 10, 655380, 2, 655398, 7, 655401, 8, 655412, 536870925, 655413, 11, 655414, 13, 655430, 536870914, 655431, 10, 655432, 10, 655433, 10, 655434, 10, 655435, 10, 655436, 10, 655437, 10, 655438, 10, 720896, 2, 720912, 536870914, 720913, 10, 720914, 10, 720915, 10, 720916, 2, 720934, 8, 720937, 7, 720958, 536870913, 720959, 5, 720960, 536870917, 720961, 5, 720962, 5, 720963, 536870917, 720964, 5, 720965, 0, 720966, 536870916, 720967, 10, 720968, 10, 720969, 10, 720970, 10, 720971, 10, 720972, 10, 720973, 10, 720974, 10, 786432, 2, 786437, 9, 786448, 536870914, 786449, 10, 786450, 10, 786451, 10, 786452, 2, 786464, 536870913, 786465, 1, 786470, 7, 786473, 7, 786474, 536870924, 786475, 1, 786494, 536870914, 786495, 10, 786496, 10, 786497, 10, 786498, 10, 786499, 10, 786500, 10, 786501, 10, 786502, 10, 786503, 10, 786504, 10, 786505, 10, 786506, 10, 786507, 10, 786508, 10, 786509, 10, 851968, 2, 851973, 7, 851984, 536870914, 851985, 10, 851986, 10, 851987, 10, 851988, 2, 851996, 536870913, 851997, 1, 852000, 536870914, 852001, 3, 852006, 7, 852009, 536870913, 852011, 2, 852030, 536870914, 852031, 10, 852032, 10, 852033, 10, 852034, 10, 852035, 10, 852036, 10, 852037, 10, 852038, 10, 852039, 10, 852040, 10, 852041, 10, 852042, 10, 852043, 10, 852044, 10, 852045, 10, 917504, 2, 917506, 9, 917509, 7, 917512, 536870921, 917520, 536870925, 917521, 11, 917522, 11, 917523, 11, 917524, 13, 917532, 536870925, 917533, 13, 917536, 536870914, 917537, 4, 917538, 1, 917540, 536870913, 917541, 0, 917542, 1, 917545, 536870914, 917546, 10, 917547, 4, 917548, 1, 917566, 536870914, 917567, 10, 917568, 10, 917569, 10, 917570, 10, 917571, 10, 917572, 10, 917573, 10, 917574, 10, 917575, 10, 917576, 10, 917577, 10, 917578, 10, 917579, 10, 917580, 10, 917581, 10, 983040, 2, 983042, 7, 983045, 7, 983048, 536870920, 983050, 536870913, 983051, 0, 983052, 1, 983064, 536870913, 983065, 1, 983072, 536870914, 983073, 10, 983074, 4, 983075, 0, 983076, 536870916, 983077, 10, 983078, 4, 983079, 536870912, 983080, 536870912, 983081, 536870916, 983082, 10, 983083, 10, 983084, 2, 983095, 9, 983102, 536870914, 983103, 10, 983104, 10, 983105, 10, 983106, 10, 983107, 10, 983108, 10, 983109, 10, 983110, 10, 983111, 10, 983112, 10, 983113, 10, 983114, 10, 983115, 10, 983116, 10, 983117, 10, 1048576, 2, 1048578, 8, 1048581, 8, 1048584, 536870919, 1048586, 536870914, 1048587, 536870922, 1048588, 2, 1048600, 536870925, 1048601, 13, 1048604, 9, 1048608, 536870925, 1048609, 536870923, 1048610, 536870923, 1048611, 536870923, 1048612, 10, 1048613, 10, 1048614, 10, 1048615, 10, 1048616, 10, 1048617, 10, 1048618, 10, 1048619, 10, 1048620, 4, 1048621, 1, 1048630, 536870921, 1048631, 8, 1048638, 536870914, 1048639, 10, 1048640, 10, 1048641, 10, 1048642, 10, 1048643, 10, 1048644, 10, 1048645, 10, 1048646, 10, 1048647, 10, 1048648, 10, 1048649, 10, 1048650, 10, 1048651, 10, 1048652, 10, 1048653, 10, 1114112, 4, 1114113, 0, 1114114, 6, 1114115, 0, 1114116, 0, 1114117, 6, 1114118, 1, 1114120, 536870920, 1114122, 536870925, 1114123, 11, 1114124, 13, 1114128, 536870913, 1114129, 5, 1114130, 536870917, 1114131, 5, 1114132, 0, 1114133, 1, 1114140, 7, 1114141, 536870921, 1114148, 536870914, 1114149, 10, 1114150, 10, 1114151, 10, 1114152, 10, 1114153, 10, 1114154, 10, 1114155, 10, 1114156, 10, 1114157, 2, 1114166, 536870920, 1114167, 8, 1114174, 536870914, 1114175, 10, 1114176, 10, 1114177, 10, 1114178, 10, 1114179, 10, 1114180, 10, 1114181, 10, 1114182, 10, 1114183, 10, 1114184, 10, 1114185, 10, 1114186, 10, 1114187, 10, 1114188, 10, 1179648, 10, 1179649, 10, 1179650, 10, 1179651, 10, 1179652, 10, 1179653, 10, 1179654, 2, 1179656, 536870919, 1179664, 536870915, 1179665, 10, 1179666, 10, 1179667, 10, 1179668, 10, 1179669, 4, 1179670, 12, 1179675, 9, 1179676, 8, 1179677, 8, 1179684, 536870914, 1179685, 10, 1179686, 10, 1179687, 10, 1179688, 10, 1179689, 10, 1179690, 10, 1179691, 10, 1179692, 10, 1179693, 4, 1179694, 1, 1179701, 9, 1179702, 536870919, 1179703, 7, 1179710, 536870914, 1179711, 10, 1179712, 10, 1179713, 10, 1179714, 10, 1179715, 10, 1179716, 10, 1179717, 10, 1179718, 10, 1179719, 10, 1179720, 10, 1179721, 10, 1179722, 10, 1245184, 10, 1245185, 10, 1245186, 10, 1245187, 10, 1245188, 10, 1245189, 10, 1245190, 2, 1245192, 536870919, 1245199, 536870913, 1245200, 536870916, 1245201, 10, 1245202, 10, 1245203, 10, 1245204, 10, 1245205, 10, 1245207, 1, 1245211, 7, 1245212, 7, 1245213, 536870920, 1245220, 536870914, 1245221, 10, 1245222, 10, 1245223, 10, 1245224, 10, 1245225, 10, 1245226, 10, 1245227, 10, 1245228, 10, 1245229, 10, 1245230, 2, 1245237, 8, 1245238, 536870919, 1245239, 8, 1245240, 536870921, 1245246, 536870914, 1245247, 10, 1245248, 10, 1245249, 10, 1245250, 10, 1245251, 10, 1245252, 10, 1245253, 10, 1245254, 10, 1245255, 10, 1245256, 10, 1245257, 10, 1245258, 10, 1310720, 10, 1310721, 10, 1310722, 10, 1310723, 10, 1310724, 10, 1310725, 10, 1310726, 2, 1310728, 536870920, 1310730, 536870913, 1310731, 1, 1310734, 536870913, 1310735, 536870916, 1310736, 10, 1310737, 10, 1310738, 10, 1310739, 10, 1310740, 10, 1310741, 10, 1310742, 10, 1310743, 4, 1310744, 1, 1310747, 8, 1310748, 7, 1310749, 536870919, 1310756, 536870914, 1310757, 10, 1310758, 10, 1310759, 10, 1310760, 10, 1310761, 10, 1310762, 10, 1310763, 10, 1310764, 10, 1310765, 10, 1310766, 4, 1310767, 5, 1310768, 12, 1310773, 7, 1310774, 536870919, 1310775, 7, 1310776, 536870919, 1310782, 536870914, 1310783, 10, 1310784, 10, 1310785, 10, 1310786, 10, 1310787, 10, 1310788, 10, 1310789, 10, 1310790, 10, 1310791, 10, 1310792, 10, 1310793, 10, 1376256, 10, 1376257, 10, 1376258, 10, 1376259, 10, 1376260, 10, 1376261, 10, 1376262, 4, 1376263, 0, 1376264, 0, 1376265, 0, 1376266, 536870916, 1376267, 4, 1376268, 0, 1376269, 0, 1376270, 536870916, 1376271, 10, 1376272, 10, 1376273, 10, 1376274, 10, 1376275, 10, 1376276, 10, 1376277, 10, 1376278, 10, 1376279, 10, 1376280, 4, 1376281, 12, 1376283, 8, 1376284, 8, 1376285, 536870920, 1376287, 536870924, 1376288, 0, 1376289, 5, 1376290, 536870917, 1376291, 0, 1376292, 536870916, 1376293, 10, 1376294, 10, 1376295, 10, 1376296, 10, 1376297, 10, 1376298, 10, 1376299, 10, 1376300, 10, 1376301, 10, 1376302, 10, 1376303, 10, 1376305, 12, 1376309, 7, 1376310, 536870920, 1376311, 7, 1376312, 536870920, 1376318, 536870914, 1376319, 10, 1376320, 10, 1376321, 10, 1376322, 10, 1376323, 10, 1376324, 10, 1376325, 10, 1376326, 10, 1376327, 10, 1376328, 10, 1441792, 10, 1441793, 10, 1441794, 10, 1441795, 10, 1441796, 10, 1441797, 10, 1441798, 10, 1441799, 10, 1441800, 10, 1441801, 10, 1441802, 10, 1441803, 10, 1441804, 10, 1441805, 10, 1441806, 10, 1441807, 10, 1441808, 10, 1441809, 10, 1441810, 10, 1441811, 10, 1441812, 10, 1441813, 10, 1441814, 10, 1441815, 10, 1441816, 10, 1441818, 0, 1441819, 6, 1441820, 6, 1441821, 536870918, 1441822, 5, 1441824, 10, 1441825, 10, 1441826, 10, 1441827, 10, 1441828, 10, 1441829, 10, 1441830, 10, 1441831, 10, 1441832, 10, 1441833, 10, 1441834, 10, 1441835, 10, 1441836, 10, 1441837, 10, 1441838, 10, 1441839, 10, 1441840, 10, 1441842, 0, 1441843, 0, 1441844, 0, 1441845, 6, 1441846, 536870918, 1441847, 6, 1441848, 536870918, 1441849, 0, 1441850, 5, 1441851, 536870917, 1441852, 5, 1441853, 0, 1441854, 536870916, 1441855, 10, 1441856, 10, 1441857, 10, 1441858, 10, 1441859, 10, 1441860, 10, 1441861, 10, 1441862, 10, 1441863, 10, 1507328, 10, 1507329, 10, 1507330, 10, 1507331, 10, 1507332, 10, 1507333, 10, 1507334, 10, 1507335, 10, 1507336, 10, 1507337, 10, 1507338, 10, 1507339, 10, 1507340, 10, 1507341, 10, 1507342, 10, 1507343, 10, 1507344, 10, 1507345, 10, 1507346, 10, 1507347, 10, 1507348, 10, 1507349, 10, 1507350, 10, 1507351, 10, 1507352, 10, 1507353, 10, 1507354, 10, 1507355, 10, 1507356, 10, 1507357, 10, 1507358, 10, 1507359, 10, 1507360, 10, 1507361, 10, 1507362, 10, 1507363, 10, 1507364, 10, 1507365, 10, 1507366, 10, 1507367, 10, 1507368, 10, 1507369, 10, 1507370, 10, 1507371, 10, 1507372, 10, 1507373, 10, 1507374, 10, 1507375, 10, 1507376, 10, 1507377, 10, 1507378, 10, 1507379, 10, 1507380, 10, 1507381, 10, 1507382, 10, 1507383, 10, 1507384, 10, 1507385, 10, 1507386, 10, 1507387, 10, 1507388, 10, 1507389, 10, 1507390, 10, 1507391, 10, 1507392, 10, 1507393, 10, 1507394, 10, 1507395, 10, 1507396, 10, 1507397, 10, 1507398, 10, 1507399, 10, 1572864, 10, 1572865, 10, 1572866, 10, 1572867, 10, 1572868, 10, 1572869, 10, 1572870, 10, 1572871, 10, 1572872, 10, 1572873, 10, 1572874, 10, 1572875, 10, 1572876, 10, 1572877, 10, 1572878, 10, 1572879, 10, 1572880, 10, 1572881, 10, 1572882, 10, 1572883, 10, 1572884, 10, 1572885, 10, 1572886, 10, 1572887, 10, 1572888, 10, 1572889, 10, 1572890, 10, 1572891, 10, 1572892, 10, 1572893, 10, 1572894, 10, 1572895, 10, 1572896, 10, 1572897, 10, 1572898, 10, 1572899, 10, 1572900, 10, 1572901, 10, 1572902, 10, 1572903, 10, 1572904, 10, 1572905, 10, 1572906, 10, 1572907, 10, 1572908, 10, 1572909, 10, 1572910, 10, 1572911, 10, 1572912, 10, 1572913, 10, 1572914, 10, 1572915, 10, 1572916, 10, 1572917, 10, 1572918, 10, 1572919, 10, 1572920, 10, 1572921, 10, 1572922, 10, 1572923, 10, 1572924, 10, 1572925, 10, 1572926, 10, 1572927, 10, 1572928, 10, 1572929, 10, 1572930, 10, 1572931, 10, 1572932, 10, 1572933, 10, 1572934, 10, 1572935, 10, 1638400, 10, 1638401, 10, 1638402, 10, 1638403, 10, 1638404, 10, 1638405, 10, 1638406, 10, 1638407, 10, 1638408, 10, 1638409, 10, 1638410, 10, 1638411, 10, 1638412, 10, 1638413, 10, 1638414, 10, 1638415, 10, 1638416, 10, 1638417, 10, 1638418, 10, 1638419, 10, 1638420, 10, 1638421, 10, 1638422, 10, 1638423, 10, 1638424, 10, 1638425, 10, 1638426, 10, 1638427, 10, 1638428, 10, 1638429, 10, 1638430, 10, 1638431, 10, 1638432, 10, 1638433, 10, 1638434, 10, 1638435, 10, 1638436, 10, 1638437, 10, 1638438, 10, 1638439, 10, 1638440, 10, 1638441, 10, 1638442, 10, 1638443, 10, 1638444, 10, 1638445, 10, 1638446, 10, 1638447, 10, 1638448, 10, 1638449, 10, 1638450, 10, 1638451, 10, 1638452, 10, 1638453, 10, 1638454, 10, 1638455, 10, 1638456, 10, 1638457, 10, 1638458, 10, 1638459, 10, 1638460, 10, 1638461, 10, 1638462, 10, 1638463, 10, 1638464, 10, 1638465, 10, 1638466, 10, 1638467, 10, 1638468, 10, 1638469, 10, 1638470, 10, 1638471, 10, 1703952, 10, 1703953, 10, 1703954, 10, 1703955, 10, 1703956, 10, 1703957, 10, 1703958, 10, 1703959, 10, 1703960, 10, 1703961, 10, 1703962, 10, 1703963, 10, 1703964, 10, 1703965, 10, 1703966, 10, 1703967, 10, 1703968, 10, 1703969, 10, 1703970, 10, 1703971, 10, 1703972, 10, 1703973, 10, 1703974, 10, 1703975, 10, 1703976, 10, 1703977, 10, 1703978, 10, 1703979, 10, 1703980, 10, 1703981, 10, 1703982, 10, 1703983, 10, 1703984, 10, 1703985, 10, 1703986, 10, 1703987, 10, 1703988, 10, 1703989, 10, 1703990, 10, 1703991, 10, 1703992, 10, 1703993, 10, 1703994, 10, 1703995, 10, 1703996, 10, 1703997, 10, 1703998, 10, 1703999, 10, 1704000, 10, 1704001, 10, 1704002, 10, 1704003, 10, 1704004, 10, 1704005, 10, 1704006, 10, 1704007, 10, 1769488, 10, 1769489, 10, 1769490, 10, 1769491, 10, 1769492, 10, 1769493, 10, 1769494, 10, 1769495, 10, 1769496, 10, 1769497, 10, 1769498, 10, 1769499, 10, 1769500, 10, 1769501, 10, 1769502, 10, 1769503, 10, 1769504, 10, 1769505, 10, 1769506, 10, 1769507, 10, 1769508, 10, 1769509, 10, 1769510, 10, 1769511, 10, 1769512, 10, 1769513, 10, 1769514, 10, 1769515, 10, 1769516, 10, 1769517, 10, 1769518, 10, 1769519, 10, 1769520, 10, 1769521, 10, 1769522, 10, 1769523, 10, 1769524, 10, 1769525, 10, 1769526, 10, 1769527, 10, 1769528, 10, 1769529, 10, 1769530, 10, 1769531, 10, 1769532, 10, 1769533, 10, 1769534, 10, 1769535, 10, 1769536, 10, 1769537, 10, 1769538, 10, 1769539, 10, 1769540, 10, 1769541, 10 </int_array>
<dictionary shared="false">
<string> "_edit_lock_" </string>
<bool> True </bool>
</dictionary>
<resource external="1"> </resource>
<vector2> 672, 1179 </vector2>
- <bool> True </bool>
<real> 0.1 </real>
<vector2> 704, 1179 </vector2>
<vector2> 736, 1179 </vector2>
@@ -354,6 +219,7 @@
<resource external="5"> </resource>
<vector2> 251.684, 1045.6 </vector2>
<resource external="6"> </resource>
+ <bool> True </bool>
<real> 2 </real>
<int> 500 </int>
<resource external="7"> </resource>
diff --git a/demos/3d/polygon_path_finder/engine.cfg b/demos/3d/polygon_path_finder/engine.cfg
deleted file mode 100644
index 47450408af..0000000000
--- a/demos/3d/polygon_path_finder/engine.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[application]
-
-name="Polygon Pathfinder"
-main_scene="res://poly_with_holes.scn"
-icon="res://icon.png"
diff --git a/demos/3d/polygon_path_finder/icon.png b/demos/3d/polygon_path_finder/icon.png
deleted file mode 100644
index 643f5595ee..0000000000
--- a/demos/3d/polygon_path_finder/icon.png
+++ /dev/null
Binary files differ
diff --git a/demos/3d/polygon_path_finder/poly_with_holes.scn b/demos/3d/polygon_path_finder/poly_with_holes.scn
deleted file mode 100644
index 6b340377b7..0000000000
--- a/demos/3d/polygon_path_finder/poly_with_holes.scn
+++ /dev/null
Binary files differ
diff --git a/demos/3d/polygon_path_finder/polygonpathfinder.gd b/demos/3d/polygon_path_finder/polygonpathfinder.gd
deleted file mode 100644
index 1e843043da..0000000000
--- a/demos/3d/polygon_path_finder/polygonpathfinder.gd
+++ /dev/null
@@ -1,77 +0,0 @@
-
-extends Spatial
-
-
-func _ready():
- var pf = PolygonPathFinder.new()
-
- var points = Vector2Array()
- var connections = IntArray()
-
- # Poly 1
- points.push_back(Vector2(0, 0)) # 0
- points.push_back(Vector2(10, 0)) # 1
- points.push_back(Vector2(10, 10)) # 2
- points.push_back(Vector2(0, 10)) # 3
-
- connections.push_back(0) # Connect vertex 0...
- connections.push_back(1) # ... to 1
- drawLine(points[0], points[1], get_node("/root/Spatial/Polys"))
- connections.push_back(1) # Connect vertex 1...
- connections.push_back(2) # ... to 2
- drawLine(points[1], points[2], get_node("/root/Spatial/Polys"))
- connections.push_back(2) # Etc.
- connections.push_back(3)
- drawLine(points[2], points[3], get_node("/root/Spatial/Polys"))
- connections.push_back(3) # Connect vertex 3...
- connections.push_back(0) # ... back to vertex 0, to close the polygon
- drawLine(points[3], points[0], get_node("/root/Spatial/Polys"))
-
- # Poly 2, as obstacle inside poly 1
- points.push_back(Vector2(2, 0.5)) # 4
- points.push_back(Vector2(4, 0.5)) # 5
- points.push_back(Vector2(4, 9.5)) # 6
- points.push_back(Vector2(2, 9.5)) # 7
-
- connections.push_back(4)
- connections.push_back(5)
- drawLine(points[4], points[5], get_node("/root/Spatial/Polys"))
- connections.push_back(5)
- connections.push_back(6)
- drawLine(points[5], points[6], get_node("/root/Spatial/Polys"))
- connections.push_back(6)
- connections.push_back(7)
- drawLine(points[6], points[7], get_node("/root/Spatial/Polys"))
- connections.push_back(7)
- connections.push_back(4)
- drawLine(points[7], points[4], get_node("/root/Spatial/Polys"))
-
- print("points: ", points)
- print("connections: ", connections)
-
- pf.setup(points, connections)
-
- var path = pf.find_path(Vector2(1, 5), Vector2(8, 5))
-
- var lastStep = null
- print("path: ", path)
- for step in path:
- print("step: ", step)
- if (lastStep != null):
- var currPathSegment = Vector2Array()
- drawLine(lastStep, step, get_node("/root/Spatial/Path"))
- lastStep = step
-
-
-func drawLine(pointA, pointB, immediateGeo):
- var drawPosY = 0.1
- var im = immediateGeo
-
- im.begin(Mesh.PRIMITIVE_POINTS, null)
- im.add_vertex(Vector3(pointA.x, drawPosY, pointA.y))
- im.add_vertex(Vector3(pointB.x, drawPosY, pointB.y))
- im.end()
- im.begin(Mesh.PRIMITIVE_LINE_STRIP, null)
- im.add_vertex(Vector3(pointA.x, drawPosY, pointA.y))
- im.add_vertex(Vector3(pointB.x, drawPosY, pointB.y))
- im.end()
diff --git a/doc/Makefile b/doc/Makefile
index 286a5162af..d59c77063b 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -38,7 +38,7 @@ rst:
rm -rf $(OUTPUTDIR)/rst
mkdir -p $(OUTPUTDIR)/rst
pushd $(OUTPUTDIR)/rst
- echo "TODO"
+ python2 $(TOOLSDIR)/makerst.py $(CLASSES)
popd
textile:
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index e642430636..9f12c7cb52 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<doc version="2.0.beta.custom_build" name="Engine Types">
+<doc version="2.0.rc1.custom_build" name="Engine Types">
<class name="@GDScript" category="Core">
<brief_description>
Built-in GDScript functions.
@@ -97,7 +97,7 @@
<argument index="1" name="y" type="float">
</argument>
<description>
- Arc-tangent that takes a 2D vector as argument, retuns the full -pi to +pi range.
+ Arc-tangent that takes a 2D vector as argument, returns the full -pi to +pi range.
</description>
</method>
<method name="sqrt">
@@ -344,7 +344,7 @@
<argument index="0" name="rad" type="float">
</argument>
<description>
- Convert from radias to degrees.
+ Convert from radians to degrees.
</description>
</method>
<method name="linear2db">
@@ -621,6 +621,32 @@
<description>
</description>
</method>
+ <method name="preload">
+ <return type="Resource">
+ </return>
+ <argument index="0" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="yield">
+ <return type="Nil">
+ </return>
+ <argument index="0" name="object" type="Object">
+ </argument>
+ <argument index="1" name="signal" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="assert">
+ <return type="Nil">
+ </return>
+ <argument index="0" name="condition" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
<constant name="PI" value="3.141593">
@@ -681,9 +707,9 @@
</member>
<member name="PS2D" type="Physics2DServer">
</member>
- <member name="SpatialSoundServer" type="SpatialSound2DServer">
+ <member name="SpatialSoundServer" type="SpatialSoundServer">
</member>
- <member name="SS" type="SpatialSound2DServer">
+ <member name="SS" type="SpatialSoundServer">
</member>
<member name="SpatialSound2DServer" type="SpatialSound2DServer">
</member>
@@ -825,7 +851,7 @@
</constant>
<constant name="KEY_KP_DIVIDE" value="16777346">
</constant>
- <constant name="KEY_KP_SUBSTRACT" value="16777347">
+ <constant name="KEY_KP_SUBTRACT" value="16777347">
</constant>
<constant name="KEY_KP_PERIOD" value="16777348">
</constant>
@@ -1247,6 +1273,10 @@
</constant>
<constant name="BUTTON_WHEEL_DOWN" value="5">
</constant>
+ <constant name="BUTTON_WHEEL_LEFT" value="6">
+ </constant>
+ <constant name="BUTTON_WHEEL_RIGHT" value="7">
+ </constant>
<constant name="BUTTON_MASK_LEFT" value="1">
</constant>
<constant name="BUTTON_MASK_RIGHT" value="2">
@@ -1403,7 +1433,7 @@
<constant name="JOY_ANALOG_R2" value="7">
</constant>
<constant name="OK" value="0">
- Functions that return [Error] return OK when everything went ok. Most functions don't return error anyway and/or just print errors to stdout.
+ Functions that return Error return OK when everything went ok. Most functions don't return error anyway and/or just print errors to stdout.
</constant>
<constant name="FAILED" value="1">
Generic fail return error.
@@ -1545,6 +1575,22 @@
<constant name="PROPERTY_USAGE_DEFAULT" value="7">
Default usage (storage and editor).
</constant>
+ <constant name="METHOD_FLAG_NORMAL" value="1">
+ </constant>
+ <constant name="METHOD_FLAG_EDITOR" value="2">
+ </constant>
+ <constant name="METHOD_FLAG_NOSCRIPT" value="4">
+ </constant>
+ <constant name="METHOD_FLAG_CONST" value="8">
+ </constant>
+ <constant name="METHOD_FLAG_REVERSE" value="16">
+ </constant>
+ <constant name="METHOD_FLAG_VIRTUAL" value="32">
+ </constant>
+ <constant name="METHOD_FLAG_FROM_SCRIPT" value="64">
+ </constant>
+ <constant name="METHOD_FLAGS_DEFAULT" value="1">
+ </constant>
<constant name="TYPE_NIL" value="0">
Variable is of type nil (only applied for null).
</constant>
@@ -1760,7 +1806,7 @@
<argument index="0" name="with" type="AABB">
</argument>
<description>
- Return the intersection between two [AABB]s. An empty AABB (size 0,0,0) is returned on failure.
+ Return the intersection between two [AABB]. An empty AABB (size 0,0,0) is returned on failure.
</description>
</method>
<method name="intersects">
@@ -1953,7 +1999,7 @@
<return type="bool">
</return>
<description>
- Return true when centered. See [set_centered].
+ Return true when centered. See [method set_centered].
</description>
</method>
<method name="set_offset">
@@ -2081,7 +2127,8 @@
Contains data used to animate everything in the engine.
</brief_description>
<description>
- An Animation resource contains data used to animate everything in the engine. Animations are divided into tracks, and each track must be linked to a node. The state of that node can be changed through time, by adding timed keys (events) to the track. [br] Animations are just data containers, and must be added to odes such as an [AnimationPlayer] or [AnimationTreePlayer] to be played back.
+ An Animation resource contains data used to animate everything in the engine. Animations are divided into tracks, and each track must be linked to a node. The state of that node can be changed through time, by adding timed keys (events) to the track.
+ Animations are just data containers, and must be added to odes such as an [AnimationPlayer] or [AnimationTreePlayer] to be played back.
</description>
<methods>
<method name="add_track">
@@ -2092,7 +2139,7 @@
<argument index="1" name="at_pos" type="int" default="-1">
</argument>
<description>
- Add a track to the Animation. The track type must be specified as any of the values in te TYPE_* enumeration.
+ Add a track to the Animation. The track type must be specified as any of the values in the TYPE_* enumeration.
</description>
</method>
<method name="remove_track">
@@ -2155,7 +2202,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Nove a track down.
+ Move a track down.
</description>
</method>
<method name="transform_track_insert_key">
@@ -2325,7 +2372,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return wether interpolation is enabled or disabled for a whole track. By default tracks are interpolated.
+ Return whether interpolation is enabled or disabled for a whole track. By default tracks are interpolated.
</description>
</method>
<method name="value_track_get_key_indices" qualifiers="const">
@@ -2401,7 +2448,7 @@
<return type="bool">
</return>
<description>
- Return wether the animation has the loop flag set.
+ Return whether the animation has the loop flag set.
</description>
</method>
<method name="set_step">
@@ -2448,7 +2495,7 @@
Container and player of [Animation] resources.
</brief_description>
<description>
- An animation player is used for general purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in diferent channels.
+ An animation player is used for general purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in different channels.
</description>
<methods>
<method name="add_animation">
@@ -2484,7 +2531,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Request wether an [Animation] name exist within the player.
+ Request whether an [Animation] name exist within the player.
</description>
</method>
<method name="get_animation" qualifiers="const">
@@ -2511,7 +2558,7 @@
<argument index="2" name="sec" type="float">
</argument>
<description>
- Specify a blend time (in seconds) between two animations, referemced by their names.
+ Specify a blend time (in seconds) between two animations, referenced by their names.
</description>
</method>
<method name="get_blend_time" qualifiers="const">
@@ -2522,7 +2569,7 @@
<argument index="1" name="anim_to" type="String">
</argument>
<description>
- Get the blend time between two animations, referemced by their names.
+ Get the blend time between two animations, referenced by their names.
</description>
</method>
<method name="set_default_blend_time">
@@ -2575,7 +2622,7 @@
<return type="bool">
</return>
<description>
- Return wether an animation is playing.
+ Return whether an animation is playing.
</description>
</method>
<method name="set_current_animation">
@@ -2658,7 +2705,7 @@
<return type="NodePath">
</return>
<description>
- Return path to root node (see [set_root]).
+ Return path to root node (see [method set_root]).
</description>
</method>
<method name="seek">
@@ -3793,7 +3840,7 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
- This signal triggers only once when a body enters this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape of the body that entered this area, and the fourth one is the index of the shape in this area that repored the entering.
+ This signal triggers only once when a body enters this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape of the body that entered this area, and the fourth one is the index of the shape in this area that reported the entering.
</description>
</signal>
<signal name="area_enter">
@@ -3891,7 +3938,7 @@
<argument index="0" name="value" type="var">
</argument>
<description>
- Remove the first occurence of a value from the array.
+ Remove the first occurrence of a value from the array.
</description>
</method>
<method name="find">
@@ -4173,7 +4220,7 @@
<argument index="1" name="data" type="RealArray">
</argument>
<description>
- Set the sample data for a given sample as an array of floats. The length must be equal to the sample lenght or an error will be produced.
+ Set the sample data for a given sample as an array of floats. The length must be equal to the sample length or an error will be produced.
For this method, a stereo sample is made from two samples. Thus, in case of a stereo sample, the array length must be twice the length returned by [method sample_get_length].
Trying to alter a SAMPLE_FORMAT_IMA_ADPCM sample is not supported. It will throw an error to the console, but will not alter the sample data.
</description>
@@ -4184,8 +4231,8 @@
<argument index="1" name="data" type="RawArray">
</argument>
<description>
- Set the sample data for a given sample as an array of bytes. The length must be equal to the sample lenght expected in bytes or an error will be produced. The byte length can be calculated as follows:
- Get the sample length ([method get_sample_length]).
+ Set the sample data for a given sample as an array of bytes. The length must be equal to the sample length expected in bytes or an error will be produced. The byte length can be calculated as follows:
+ Get the sample length ([method sample_get_length]).
If the sample format is SAMPLE_FORMAT_PCM16, multiply it by 2.
If the sample format is SAMPLE_FORMAT_IMA_ADPCM, divide it by 2 (rounding any fraction up), then add 4.
If the sample is stereo ([method sample_is_stereo]), multiply it by 2.
@@ -4360,7 +4407,7 @@
<argument index="1" name="enabled" type="bool">
</argument>
<description>
- Set wether a given voice is positional. This is only interpreted as a hint and used for backends that may support binaural encoding.
+ Set whether a given voice is positional. This is only interpreted as a hint and used for backends that may support binaural encoding.
</description>
</method>
<method name="voice_get_volume" qualifiers="const">
@@ -4468,7 +4515,7 @@
<argument index="0" name="voice" type="RID">
</argument>
<description>
- Return wether the current voice is positional. See [method voice_set_positional].
+ Return whether the current voice is positional. See [method voice_set_positional].
</description>
</method>
<method name="voice_stop">
@@ -4597,7 +4644,7 @@
Base class for audio streams.
</brief_description>
<description>
- Base class for audio streams. Audio streams are used for music playback, or other types of streamed sounds that don't fit or requiere more flexibility than a [Sample].
+ Base class for audio streams. Audio streams are used for music playback, or other types of streamed sounds that don't fit or require more flexibility than a [Sample].
</description>
<methods>
</methods>
@@ -5145,7 +5192,7 @@
Provides a base class for different kinds of buttons.
</brief_description>
<description>
- BaseButton is the abstract base class for buttons, so it shouldn't be used directly (It doesnt display anything). Other types of buttons inherit from it.
+ BaseButton is the abstract base class for buttons, so it shouldn't be used directly (It doesn't display anything). Other types of buttons inherit from it.
</description>
<methods>
<method name="_pressed" qualifiers="virtual">
@@ -5203,14 +5250,14 @@
<return type="bool">
</return>
<description>
- Return wether the button is in disabled state (see [method set_disabled]).
+ Return whether the button is in disabled state (see [method set_disabled]).
</description>
</method>
<method name="set_click_on_press">
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set the button click_on_press mode. This mode generates click events when a mousebutton or key is just pressed (by default events are generated when the button/keys are released and both press and release occur in the visual area of the Button).
+ Set the button click_on_press mode. This mode generates click events when a mouse button or key is just pressed (by default events are generated when the button/keys are released and both press and release occur in the visual area of the Button).
</description>
</method>
<method name="get_click_on_press" qualifiers="const">
@@ -5224,7 +5271,7 @@
<return type="int">
</return>
<description>
- Return the visual state used to draw the button. This is useful mainly when implementing your own draw code by either overiding _draw() or connecting to "draw" signal. The visual state of the button is defined by the DRAW_* enum.
+ Return the visual state used to draw the button. This is useful mainly when implementing your own draw code by either overriding _draw() or connecting to "draw" signal. The visual state of the button is defined by the DRAW_* enum.
</description>
</method>
</methods>
@@ -5386,7 +5433,7 @@
Standard themed Button.
</brief_description>
<description>
- Button is just the standard themed button: [image src="images/button_example.png"/] It can contain text and an icon, and will display them according to the current [Theme].
+ Button is the standard themed button. It can contain text and an icon, and will display them according to the current [Theme].
</description>
<methods>
<method name="set_text">
@@ -5419,7 +5466,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set the [i]flat[/i] property of a Button. Flat buttons don't display decoration unless hoevered or pressed.
+ Set the [i]flat[/i] property of a Button. Flat buttons don't display decoration unless hovered or pressed.
</description>
</method>
<method name="set_clip_text">
@@ -5488,7 +5535,7 @@
Array of Buttons.
</brief_description>
<description>
- Array of Buttons. A Button array is useful to have an array of buttons laid out vertically or horizontally. Only one can be selected. This is useful for joypad based interfaces and option menus.
+ Array of Buttons. A Button array is useful to have an array of buttons laid out vertically or horizontally. Only one can be selected. This is useful for joy pad based interfaces and option menus.
</description>
<methods>
<method name="add_button">
@@ -5566,7 +5613,7 @@
<argument index="0" name="button" type="int">
</argument>
<description>
- Sekect a button in the array.
+ Select a button in the array.
</description>
</method>
<method name="erase_button">
@@ -5593,7 +5640,7 @@
</signals>
<constants>
<constant name="ALIGN_BEGIN" value="0">
- Align buttons at the begining.
+ Align buttons at the beginning.
</constant>
<constant name="ALIGN_CENTER" value="1">
Align buttons in the middle.
@@ -5614,7 +5661,7 @@
Group of Buttons.
</brief_description>
<description>
- Group of [Button]s. All direct and indirect children buttons become radios. Only one allows being pressed.
+ Group of [Button]. All direct and indirect children buttons become radios. Only one allows being pressed.
</description>
<methods>
<method name="get_pressed_button" qualifiers="const">
@@ -5665,7 +5712,7 @@
Camera node, displays from a point of view.
</brief_description>
<description>
- Camera is a special node that displays what is visible from its current location. Cameras register themselves in the nearest [Viewport] node (when ascending the tree). Only one camera can be active per viewport. If no viewport is available ascending the tree, the Camera will register in the global viewport. In other words, a Camera just provides [i]3D[/i] display capabilities to a [Viewport], and, without one, a [Scene] registered in that [Viewport] (or higher viewports) can't be displayed.
+ Camera is a special node that displays what is visible from its current location. Cameras register themselves in the nearest [Viewport] node (when ascending the tree). Only one camera can be active per viewport. If no viewport is available ascending the tree, the Camera will register in the global viewport. In other words, a Camera just provides [i]3D[/i] display capabilities to a [Viewport], and, without one, a scene registered in that [Viewport] (or higher viewports) can't be displayed.
</description>
<methods>
<method name="project_ray_normal" qualifiers="const">
@@ -5700,7 +5747,7 @@
<argument index="0" name="world_point" type="Vector3">
</argument>
<description>
- Return how a 3D point in worldpsace maps to a 2D coordinate in the [Viewport] rectangle.
+ Return how a 3D point in worldspace maps to a 2D coordinate in the [Viewport] rectangle.
</description>
</method>
<method name="is_position_behind" qualifiers="const">
@@ -5754,7 +5801,7 @@
<return type="bool">
</return>
<description>
- Return wether the Camera is the current one in the [Viewport], or plans to become current (if outside the scene tree).
+ Return whether the Camera is the current one in the [Viewport], or plans to become current (if outside the scene tree).
</description>
</method>
<method name="get_camera_transform" qualifiers="const">
@@ -5904,7 +5951,7 @@
<return type="bool">
</return>
<description>
- Return true of this is the current camera (see [method Camera2D.make_current]).
+ Return true of this is the current camera (see [method make_current]).
</description>
</method>
<method name="set_limit">
@@ -6059,7 +6106,7 @@
</brief_description>
<description>
Base class of anything 2D. Canvas items are laid out in a tree and children inherit and extend the transform of their parent. CanvasItem is extended by [Control], for anything GUI related, and by [Node2D] for anything 2D engine related.
- Any CanvasItem can draw. For this, the "update" function must be called, then NOTIFICATION_DRAW will be received on idle time to request redraw. Because of this, canvas items don't need to be redraw on every frame, improving the performance significan'tly. Several functions for drawing on the CanvasItem are provided (see draw_* functions). They can only be used inside the notification, signal or _draw() overrided function, though.
+ Any CanvasItem can draw. For this, the "update" function must be called, then NOTIFICATION_DRAW will be received on idle time to request redraw. Because of this, canvas items don't need to be redraw on every frame, improving the performance significan'tly. Several functions for drawing on the CanvasItem are provided (see draw_* functions). They can only be used inside the notification, signal or _draw() overrides function, though.
Canvas items are draw in tree order. By default, children are on top of their parents so a root CanvasItem will be drawn behind everything (this can be changed per item though).
Canvas items can also be hidden (hiding also their subtree). They provide many means for changing standard parameters such as opacity (for it and the subtree) and self opacity, blend mode.
Ultimately, a transform notification can be requested, which will notify the node that its global position changed in case the parent tree changed.
@@ -6074,7 +6121,7 @@
<argument index="0" name="state" type="var">
</argument>
<description>
- Used for editing, returns an opaque value represeting the transform state.
+ Used for editing, returns an opaque value representing the transform state.
</description>
</method>
<method name="edit_get" qualifiers="const">
@@ -6154,7 +6201,7 @@
<return type="bool">
</return>
<description>
- Return if set as toplevel. See [method set_as_toplevel]/
+ Return if set as toplevel. See [method set_as_toplevel].
</description>
</method>
<method name="set_blend_mode">
@@ -6488,7 +6535,7 @@
<signals>
<signal name="item_rect_changed">
<description>
- Emitted when the intem rect has changed.
+ Emitted when the item rect has changed.
</description>
</signal>
<signal name="draw">
@@ -6777,7 +6824,7 @@
Capsule 2D shape resource for physics.
</brief_description>
<description>
- Capsule 2D shape resource for physics. A capsule (or sometimes called "pill") is like a line grown in all directions. It has a radius and a height, and is often useful for modelling biped characters.
+ Capsule 2D shape resource for physics. A capsule (or sometimes called "pill") is like a line grown in all directions. It has a radius and a height, and is often useful for modeling biped characters.
</description>
<methods>
<method name="set_radius">
@@ -6927,7 +6974,7 @@
Circular Shape for 2D Physics.
</brief_description>
<description>
- Circular Shape for 2D Physics. This shape is useful for modelling balls or small characters and it's collision detection with everything else is very fast.
+ Circular Shape for 2D Physics. This shape is useful for modeling balls or small characters and it's collision detection with everything else is very fast.
</description>
<methods>
<method name="set_radius">
@@ -7318,7 +7365,7 @@
</argument>
<description>
Set the array of points forming the polygon.
- When editing the point list via the editor, depending on [method get_build_mode], it has to be a list of points (for [code]build_mode[/code]=0), or a list of lines (for [code]build_mode[/code]=1). In the second case, the even elements of the array define the start point of the line, and the odd elements the end point.
+ When editing the point list via the editor, depending on [method get_build_mode], it has to be a list of points (for [code]build_mode==0[/code]), or a list of lines (for [code]build_mode==1[/code]). In the second case, the even elements of the array define the start point of the line, and the odd elements the end point.
</description>
</method>
<method name="get_polygon" qualifiers="const">
@@ -7332,14 +7379,14 @@
<argument index="0" name="build_mode" type="int">
</argument>
<description>
- Set whether the polygon is to be a [ConvexPolygon2D] ([code]build_mode[/code]=0), or a [ConcavePolygon2D] ([code]build_mode[/code]=1).
+ Set whether the polygon is to be a [ConvexPolygonShape2D] ([code]build_mode==0[/code]), or a [ConcavePolygonShape2D] ([code]build_mode==1[/code]).
</description>
</method>
<method name="get_build_mode" qualifiers="const">
<return type="int">
</return>
<description>
- Return whether the polygon is a [ConvexPolygon2D] ([code]build_mode[/code]=0), or a [ConcavePolygon2D] ([code]build_mode[/code]=1).
+ Return whether the polygon is a [ConvexPolygonShape2D] ([code]build_mode==0[/code]), or a [ConcavePolygonShape2D] ([code]build_mode==1[/code]).
</description>
</method>
<method name="set_trigger">
@@ -7361,7 +7408,7 @@
</return>
<description>
Return the index of the first shape generated by the editor.
- When [code]build_mode[/code] is set to generate convex polygons, the shape shown in the editor may be decomopsed into many convex polygons. In that case, a range of indexes is needed to directly access the [Shape2D]s.
+ When [code]build_mode[/code] is set to generate convex polygons, the shape shown in the editor may be decomposed into many convex polygons. In that case, a range of indexes is needed to directly access the [Shape2D].
When [code]build_mode[/code] is set to generate concave polygons, there is only one [Shape2D] generated, so the start index and the end index are the same.
</description>
</method>
@@ -7525,7 +7572,7 @@
<return type="int">
</return>
<description>
- Convert the color to a 32 its integer (each byte represets a RGBA).
+ Convert the color to a 32 its integer (each byte represents a RGBA).
</description>
</method>
<method name="to_ARGB32">
@@ -8084,7 +8131,7 @@
Dialog for confirmation of actions.
</brief_description>
<description>
- Dialog for confirmation of actions. This dialog inherits from [AcceptDialog], but has by default an OK and Cancel buton (in host OS order).
+ Dialog for confirmation of actions. This dialog inherits from [AcceptDialog], but has by default an OK and Cancel button (in host OS order).
</description>
<methods>
<method name="get_cancel">
@@ -8103,8 +8150,8 @@
Base node for containers.
</brief_description>
<description>
- Base node for conainers. A [Container] contains other controls and automatically arranges them in a certain way.
- A Control can inherit this to reate custom container classes.
+ Base node for containers. A [Container] contains other controls and automatically arranges them in a certain way.
+ A Control can inherit this to create custom container classes.
</description>
<methods>
<method name="queue_sort">
@@ -8125,7 +8172,7 @@
<signals>
<signal name="sort_children">
<description>
- Enmitted when sorting the children is needed.
+ Emitted when sorting the children is needed.
</description>
</signal>
</signals>
@@ -8143,7 +8190,7 @@
Control is the base class Node for all the GUI components. Every GUI component inherits from it, directly or indirectly. In this way, sections of the scene tree made of contiguous control nodes, become user interfaces.
Controls are relative to the parent position and size by using anchors and margins. This ensures that they can adapt easily in most situation to changing dialog and screen sizes. When more flexibility is desired, [Container] derived nodes can be used.
Anchors work by defining which margin do they follow, and a value relative to it. Allowed anchoring modes are ANCHOR_BEGIN, where the margin is relative to the top or left margins of the parent (in pixels), ANCHOR_END for the right and bottom margins of the parent and ANCHOR_RATIO, which is a ratio from 0 to 1 in the parent range.
- Input device events ([InputEvent]) are first sent to the root controls via the [method Node._input], which distribute it through the tree, then delivers them to the adequate one (under cursor or keyboard focus based) by calling [Node._input_event]. There is no need to enable input processing on controls to receive such events. To ensure that no one else will receive the event (not even [method Node._unhandled_input]), the control can accept it by calling [method accept_event].
+ Input device events ([InputEvent]) are first sent to the root controls via the [method Node._input], which distribute it through the tree, then delivers them to the adequate one (under cursor or keyboard focus based) by calling [method MainLoop._input_event]. There is no need to enable input processing on controls to receive such events. To ensure that no one else will receive the event (not even [method Node._unhandled_input]), the control can accept it by calling [method accept_event].
Only one control can hold the keyboard focus (receiving keyboard events), for that the control must define the focus mode with [method set_focus_mode]. Focus is lost when another control gains it, or the current focus owner is hidden.
It is sometimes desired for a control to ignore mouse/pointer events. This is often the case when placing other controls on top of a button, in such cases. Calling [method set_ignore_mouse] enables this function.
Finally, controls are skinned according to a [Theme]. Setting a [Theme] on a control will propagate all the skinning down the tree. Optionally, skinning can be overrided per each control by calling the add_*_override functions, or from the editor.
@@ -8213,7 +8260,7 @@
<argument index="1" name="anchor_mode" type="int">
</argument>
<description>
- Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Changing the anchor mode converts the current margin offset from the previos anchor mode to the new one, so margin offsets ([method set_margin]) must be done after setting anchors, or at the same time ([method set_anchor_and_margin]).
+ Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Changing the anchor mode converts the current margin offset from the previous anchor mode to the new one, so margin offsets ([method set_margin]) must be done after setting anchors, or at the same time ([method set_anchor_and_margin]).
</description>
</method>
<method name="get_anchor" qualifiers="const">
@@ -8324,7 +8371,7 @@
<return type="Vector2">
</return>
<description>
- Returns the Control position, relative to the top-left corner of the parent Control and independly of the anchor mode.
+ Returns the Control position, relative to the top-left corner of the parent Control and independent of the anchor mode.
</description>
</method>
<method name="get_size" qualifiers="const">
@@ -8369,28 +8416,28 @@
<return type="Rect2">
</return>
<description>
- Return position and size of the Control, relative to the top-left corner of the parent Control. This is a helper (see [method get_pos],[method get_size]).
+ Return position and size of the Control, relative to the top-left corner of the parent Control. This is a helper (see [method get_pos], [method get_size]).
</description>
</method>
<method name="get_global_rect" qualifiers="const">
<return type="Rect2">
</return>
<description>
- Return position and size of the Control, relative to the top-left corner of the [i]window[/i] Control. This is a helper (see [method get_global_pos],[method get_size]).
+ Return position and size of the Control, relative to the top-left corner of the [i]window[/i] Control. This is a helper (see [method get_global_pos], [method get_size]).
</description>
</method>
<method name="set_area_as_parent_rect">
<argument index="0" name="margin" type="int" default="0">
</argument>
<description>
- Change all margins and anchors, so this Control always takes up the same area as the parent Control. This is a helper (see [method set_anchor],[method set_margin]).
+ Change all margins and anchors, so this Control always takes up the same area as the parent Control. This is a helper (see [method set_anchor], [method set_margin]).
</description>
</method>
<method name="show_modal">
<argument index="0" name="exclusive" type="bool" default="false">
</argument>
<description>
- Display a Control as modal. Control must be a subwindow (see [method set_as_subwindow]). Modal controls capture the input signals until closed or the area outside them is accessed. When a modal control loses focus, or the ESC key is pressed, they automatically hide. Modal controls are used extensively for popup dialogs and menus.
+ Display a Control as modal. Control must be a subwindow. Modal controls capture the input signals until closed or the area outside them is accessed. When a modal control loses focus, or the ESC key is pressed, they automatically hide. Modal controls are used extensively for popup dialogs and menus.
</description>
</method>
<method name="set_focus_mode">
@@ -8404,7 +8451,7 @@
<return type="bool">
</return>
<description>
- Return wether the Control is the current focused control (see [method set_focus_mode]).
+ Return whether the Control is the current focused control (see [method set_focus_mode]).
</description>
</method>
<method name="grab_focus">
@@ -9218,7 +9265,7 @@ If "atpos" is given, the point is inserted before the point number "atpos", movi
</argument>
<description>
Sets the tilt angle in radians for the point "idx". If the index is out of bounds, the function sends an error to the console.
-The tilt controls the rotation along the look-at axis an object travelling the path would have. In the case of a curve controlling a [PathFollow], this tilt is an offset over the natural tilt the PathFollow calculates.
+The tilt controls the rotation along the look-at axis an object traveling the path would have. In the case of a curve controlling a [PathFollow], this tilt is an offset over the natural tilt the PathFollow calculates.
</description>
</method>
<method name="get_point_tilt" qualifiers="const">
@@ -9365,7 +9412,7 @@ This approximation makes straight segments between each point, then subdivides t
Damped spring constraint for 2D physics.
</brief_description>
<description>
- Damped spring constraint for 2D physics. This resembles a spring joint that always want to go back to a given length.
+ Damped spring constraint for 2D physics. This resembles a spring joint that always wants to go back to a given length.
</description>
<methods>
<method name="set_length">
@@ -9400,28 +9447,28 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="stiffness" type="float">
</argument>
<description>
- Set the stiffness of the spring joint.
+ Set the stiffness of the spring joint. The joint applies a force equal to the stiffness times the distance from its resting length.
</description>
</method>
<method name="get_stiffness" qualifiers="const">
<return type="float">
</return>
<description>
- Return the stiffness of the spring joint.
+ Return the stiffness of the spring joint. The joint applies a force equal to the stiffness times the distance from its resting length.
</description>
</method>
<method name="set_damping">
<argument index="0" name="damping" type="float">
</argument>
<description>
- Set the damping of the spring joint.
+ Set the damping ratio of the spring joint. A value of 0 indicates an undamped spring, while 1 causes the system to reach equilibrium as fast as possible (critical damping).
</description>
</method>
<method name="get_damping" qualifiers="const">
<return type="float">
</return>
<description>
- Return the damping of the spring joint.
+ Return the damping ratio of the spring joint. A value of 0 indicates an undamped spring, while 1 causes the system to reach equilibrium as fast as possible (critical damping).
</description>
</method>
</methods>
@@ -9559,8 +9606,26 @@ This approximation makes straight segments between each point, then subdivides t
</class>
<class name="Directory" inherits="Reference" category="Core">
<brief_description>
+ Type used to handle the filesystem.
</brief_description>
<description>
+ Directory type. Is used to manage directories and their content (not restricted to the project folder).
+ Example for how to iterate through the files of a directory:
+ [codeblock]
+ func dir(path):
+ var d = Directory.new()
+ if d.open( path )==0:
+ d.list_dir_begin()
+ var file_name = d.get_next()
+ while(file_name!=""):
+ if d.current_is_dir():
+ print("Found directory: " + file_name)
+ else:
+ print("Found file:" + file_name)
+ file_name = d.get_next()
+ else:
+ print("Some open Error, maybe directory not found?")
+ [/codeblock]
</description>
<methods>
<method name="open">
@@ -9569,28 +9634,34 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="path" type="String">
</argument>
<description>
+ Opens a directory to work with. Needs a path, example "res://folder"
</description>
</method>
<method name="list_dir_begin">
<return type="bool">
</return>
<description>
+ Loads all file names of the current directory (prepares the get_next() function).
</description>
</method>
<method name="get_next">
<return type="String">
</return>
<description>
+ Is used to iterate through the files of the current directory. Returns the name(no path) of the current file/directory, it also contains "." and ".." .
+Returns an empty String "" at the end of the list.
</description>
</method>
<method name="current_is_dir" qualifiers="const">
<return type="bool">
</return>
<description>
+ Returns true if the current file you are looking at with get_next() is a directory or "." or ".." otherwise false.
</description>
</method>
<method name="list_dir_end">
<description>
+ Run this to empty the list of remaining files in get_next(). You can use it to end the iteration, as soon as your goal is reached.
</description>
</method>
<method name="get_drive_count">
@@ -9613,12 +9684,14 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="todir" type="String">
</argument>
<description>
+ Needs a path or name to the next directory. When the target directory is in the current directory you can use "newfolder" otherwise you need the full path "res://currentfolder/newfolder"
</description>
</method>
<method name="get_current_dir">
<return type="String">
</return>
<description>
+ Returns a path to the current directory, example: "res://folder"
</description>
</method>
<method name="make_dir">
@@ -9651,6 +9724,7 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="name" type="String">
</argument>
<description>
+ Returns true if directory exists otherwise false. Needs a path, example: "res://folder"
</description>
</method>
<method name="get_space_left">
@@ -10312,7 +10386,7 @@ This approximation makes straight segments between each point, then subdivides t
</argument>
<description>
Set the playback volume for this player. This is a float between 0.0 (silent) and 1.0 (full volume). Values over 1.0 may amplify sound even more, but may introduce distortion. Negative values may just invert the output waveform, which produces no audible difference.
- The effect of these special values uiltimately depends on the low-level implementation of the file format being played.
+ The effect of these special values ultimately depends on the low-level implementation of the file format being played.
</description>
</method>
<method name="get_volume" qualifiers="const">
@@ -10354,7 +10428,7 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="db" type="float">
</argument>
<description>
- Set the playback volume for this player, in decibels. This is a float between -80.0 (silent) and 0.0 (full volume). Values under -79.0 get truncated to -80, but values over 0.0 do not, so the warnings for overamplifying (see [set_volume]) still apply.
+ Set the playback volume for this player, in decibels. This is a float between -80.0 (silent) and 0.0 (full volume). Values under -79.0 get truncated to -80, but values over 0.0 do not, so the warnings for over amplifying (see [method set_volume]) still apply.
</description>
</method>
<method name="get_volume_db" qualifiers="const">
@@ -10419,7 +10493,7 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="1" name="channel_volume" type="float">
</argument>
<description>
- Set the volume scale for an individual channel of the stream, with the same value range as [methid set_volume]. The channel number depends on the stream format. For example, MIDIs range from 0 to 15, and MODs from 0 to 63.
+ Set the volume scale for an individual channel of the stream, with the same value range as [method set_volume]. The channel number depends on the stream format. For example, MIDIs range from 0 to 15, and MODs from 0 to 63.
Many stream formats are multichannel, so this allows to affect only a part of the music.
</description>
</method>
@@ -10463,10 +10537,10 @@ This approximation makes straight segments between each point, then subdivides t
Driver for MOD playback.
</brief_description>
<description>
- This driver plays MOD music. MOD music, as all event-based streams, is a music format defined by note events ocurring at defined moments, instead of a stream of audio samples.
+ This driver plays MOD music. MOD music, as all event-based streams, is a music format defined by note events occurring at defined moments, instead of a stream of audio samples.
Currently, this driver supports the MOD, S3M, IT, and XM formats.
This class exposes no methods.
- This class can return its playback positon in seconds, but does not allow to set it, failing with only a console warning.
+ This class can return its playback position in seconds, but does not allow to set it, failing with only a console warning.
This class can not return its song length, returning 1.0 when queried.
This class does not limit its volume settings, allowing for overflow/distortion and wave inversion.
</description>
@@ -10642,6 +10716,8 @@ This approximation makes straight segments between each point, then subdivides t
<method name="get_csv_line" qualifiers="const">
<return type="StringArray">
</return>
+ <argument index="0" name="delim" type="String" default="&quot;,&quot;">
+ </argument>
<description>
</description>
</method>
@@ -10906,7 +10982,7 @@ This approximation makes straight segments between each point, then subdivides t
Simple Material with a fixed parameter set.
</brief_description>
<description>
- FixedMaterial is a simple type of material [Resource], which contains a fixed amount of paramters. It is the only type of material supported in fixed-pipeline devices and APIs. It is also an often a better alternative to [ShaderMaterial] for most simple use cases.
+ FixedMaterial is a simple type of material [Resource], which contains a fixed amount of parameters. It is the only type of material supported in fixed-pipeline devices and APIs. It is also an often a better alternative to [ShaderMaterial] for most simple use cases.
</description>
<methods>
<method name="set_parameter">
@@ -11230,7 +11306,7 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="4" name="clip_w" type="int" default="-1">
</argument>
<description>
- Draw "string" into a canvas item using the font at a given "pos" position, with "modulate" color, and optionally clipping the width. "pos" specifies te baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
+ Draw "string" into a canvas item using the font at a given "pos" position, with "modulate" color, and optionally clipping the width. "pos" specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
</description>
</method>
<method name="draw_char" qualifiers="const">
@@ -11247,7 +11323,7 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="4" name="modulate" type="Color" default="Color(1,1,1,1)">
</argument>
<description>
- Draw character "char" into a canvas item using the font at a given "pos" position, with "modulate" color, and optionally kerning if "next" is apassed. clipping the width. "pos" specifies te baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. The width used by the character is returned, making this function useful for drawing strings character by character.
+ Draw character "char" into a canvas item using the font at a given "pos" position, with "modulate" color, and optionally kerning if "next" is apassed. clipping the width. "pos" specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. The width used by the character is returned, making this function useful for drawing strings character by character.
</description>
</method>
<method name="set_fallback">
@@ -11966,7 +12042,7 @@ This approximation makes straight segments between each point, then subdivides t
</brief_description>
<description>
GraphEdit manages the showing of GraphNodes it contains, as well as connections an disconnections between them. Signals are sent for each of these two events. Disconnection between GraphNodes slots is disabled by default.
- It is greatly advised to enable low processor usage mode [OS.set_low_processor_usage_mode()] when using GraphEdits.
+ It is greatly advised to enable low processor usage mode (see [method OS.set_low_processor_usage_mode]) when using GraphEdits.
</description>
<methods>
<method name="connect_node">
@@ -12104,6 +12180,16 @@ This approximation makes straight segments between each point, then subdivides t
</signals>
<constants>
</constants>
+ <theme_items>
+ <theme_item name="more" type="Texture">
+ </theme_item>
+ <theme_item name="reset" type="Texture">
+ </theme_item>
+ <theme_item name="minus" type="Texture">
+ </theme_item>
+ <theme_item name="bg" type="StyleBox">
+ </theme_item>
+ </theme_items>
</class>
<class name="GraphNode" inherits="Container" category="Core">
<brief_description>
@@ -12150,7 +12236,7 @@ This approximation makes straight segments between each point, then subdivides t
<argument index="0" name="idx" type="int">
</argument>
<description>
- Disable input and ouput slot whose index is 'idx'.
+ Disable input and output slot whose index is 'idx'.
</description>
</method>
<method name="clear_all_slots">
@@ -12863,9 +12949,8 @@ This approximation makes straight segments between each point, then subdivides t
</argument>
<description>
Connect to a host. This needs to be done before any requests are sent.
-The host should not have http:// prepended but will strip the protocol identifier if provided.
-
-verify_host will check the SSL identity of the host if set to true.
+ The host should not have http:// prepended but will strip the protocol identifier if provided.
+ verify_host will check the SSL identity of the host if set to true.
</description>
</method>
<method name="set_connection">
@@ -12886,19 +12971,15 @@ verify_host will check the SSL identity of the host if set to true.
<argument index="3" name="body" type="String" default="&quot;&quot;">
</argument>
<description>
- Sends a request to the connected host. The url is the what is normally behind the hostname, i.e:
-http://somehost.com/index.php
-url would be "index.php"
-
-Headers are HTTP request headers
-
-To create a POST request with query strings to push to the server, do:
-var fields = {"username" : "user",
- "password" : "pass"}
-var queryString = httpClient.query_string_from_dict(fields)
-var headers = ["Content-Type: application/x-www-form-urlencoded",
- "Content-Length: " + str(queryString.length())]
-var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, queryString)
+ Sends a request to the connected host. The url is what is normally behind the hostname, i.e. in [code]http://somehost.com/index.php[/code], url would be "index.php".
+ Headers are HTTP request headers.
+ To create a POST request with query strings to push to the server, do:
+ [codeblock]
+ var fields = {"username" : "user", "password" : "pass"}
+ var queryString = httpClient.query_string_from_dict(fields)
+ var headers = ["Content-Type: application/x-www-form-urlencoded", "Content-Length: " + str(queryString.length())]
+ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, queryString)
+ [/codeblock]
</description>
</method>
<method name="send_body_text">
@@ -12951,6 +13032,9 @@ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, qu
<return type="Dictionary">
</return>
<description>
+ Returns all response headers as dictionary where the case-sensitivity of the keys and values is kept like the server delivers it. A value is a simple String, this string can have more than one value where "; " is used as separator.
+Structure: ("key":"value1; value2")
+Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
</description>
</method>
<method name="get_response_body_length" qualifiers="const">
@@ -13005,12 +13089,12 @@ var result = httpClient.request(httpClient.METHOD_POST, "index.php", headers, qu
<argument index="0" name="fields" type="Dictionary">
</argument>
<description>
- Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary.
-
-var fields = {"username": "user", "password": "pass"}
-String queryString = httpClient.query_string_from_dict(fields)
-
-returns:= "username=user&amp;password=pass"
+ Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary, e.g.:
+ [codeblock]
+ var fields = {"username": "user", "password": "pass"}
+ String queryString = httpClient.query_string_from_dict(fields)
+ returns:= "username=user&amp;password=pass"
+ [/codeblock]
</description>
</method>
</methods>
@@ -13224,7 +13308,7 @@ returns:= "username=user&amp;password=pass"
IP Protocol support functions.
</brief_description>
<description>
- IP contains some support functions for the IPv4 protocol. TCP/IP support is in different classes (see [TCP_Client], [TCP_Server]). IP provides hostname resolution support, both blocking and threaded.
+ IP contains some support functions for the IPv4 protocol. TCP/IP support is in different classes (see [StreamPeerTCP] and [TCP_Server]). IP provides hostname resolution support, both blocking and threaded.
</description>
<methods>
<method name="resolve_hostname">
@@ -13731,6 +13815,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="button" type="int">
</argument>
<description>
+ Returns true or false depending on whether mouse button is pressed or not. You can pass BUTTON_*, which are pre-defined constants listed in [@Global Scope].
</description>
</method>
<method name="is_joy_button_pressed">
@@ -13741,7 +13826,7 @@ returns:= "username=user&amp;password=pass"
<argument index="1" name="button" type="int">
</argument>
<description>
- Returns if the joystick button at the given index is currently pressed. (see JOY_* constans in [@Global Scope])
+ Returns if the joystick button at the given index is currently pressed. (see JOY_* constants in [@Global Scope])
</description>
</method>
<method name="is_action_pressed">
@@ -13971,7 +14056,7 @@ returns:= "username=user&amp;password=pass"
Mouse button event.
</constant>
<constant name="JOYSTICK_MOTION" value="4">
- Jostick motion event.
+ Joystick motion event.
</constant>
<constant name="JOYSTICK_BUTTON" value="5">
Joystick button event.
@@ -14064,7 +14149,7 @@ returns:= "username=user&amp;password=pass"
</constant>
</constants>
</class>
-<class name="InputEventJoyButton" category="Built-In Types">
+<class name="InputEventJoystickButton" category="Built-In Types">
<brief_description>
</brief_description>
<description>
@@ -14150,7 +14235,7 @@ returns:= "username=user&amp;password=pass"
</constant>
</constants>
</class>
-<class name="InputEventJoyMotion" category="Built-In Types">
+<class name="InputEventJoystickMotion" category="Built-In Types">
<brief_description>
</brief_description>
<description>
@@ -15627,7 +15712,7 @@ returns:= "username=user&amp;password=pass"
<return type="Variant">
</return>
<description>
- Return the metadata of the shape that collided with this body. If there is no collision, it will return 0, so collisions must be checked first with [method is_colliding]. Aditionally, this metadata can not be set with [method Object.set_meta], it must be set with [method Physics2DServer.body_set_shape_metadata].
+ Return the metadata of the shape that collided with this body. If there is no collision, it will return 0, so collisions must be checked first with [method is_colliding]. Additionally, this metadata can not be set with [method Object.set_meta], it must be set with [method Physics2DServer.body_set_shape_metadata].
</description>
</method>
<method name="set_collision_margin">
@@ -16545,7 +16630,7 @@ returns:= "username=user&amp;password=pass"
Main loop is the abstract main loop base class.
</brief_description>
<description>
- Main loop is the abstract main loop base class. All other main loop classes are derived from it. Upon application start, a [MainLoop] has to be provided to OS, else the application will exit. This happens automatically (and a [SceneMainLoop] is created), unless a main [Script] is supplied, which may or not create and return a [MainLoop].
+ Main loop is the abstract main loop base class. All other main loop classes are derived from it. Upon application start, a [MainLoop] has to be provided to OS, else the application will exit. This happens automatically (and a [SceneTree] is created), unless a main [Script] is supplied, which may or not create and return a [MainLoop].
</description>
<methods>
<method name="_finalize" qualifiers="virtual">
@@ -17162,7 +17247,7 @@ returns:= "username=user&amp;password=pass"
Special button that brings up a [PopupMenu] when clicked.
</brief_description>
<description>
- Special button that brings up a [PopupMenu] when clicked. That's pretty much all it does, as it's just a helper class when bulding GUIs.
+ Special button that brings up a [PopupMenu] when clicked. That's pretty much all it does, as it's just a helper class when building GUIs.
</description>
<methods>
<method name="get_popup">
@@ -17211,7 +17296,7 @@ returns:= "username=user&amp;password=pass"
A [Resource] that contains vertex-array based geometry.
</brief_description>
<description>
- Mesh is a type of [Resource] that contains vertex-array based geometry, divided in [i]surfaces[/i]. Each surface contains a completely separate array and a material used to draw it. Design wise, a mesh with multiple surfaces is prefered to a single surface, because objects created in 3D editing software commonly contain multiple materials.
+ Mesh is a type of [Resource] that contains vertex-array based geometry, divided in [i]surfaces[/i]. Each surface contains a completely separate array and a material used to draw it. Design wise, a mesh with multiple surfaces is preferred to a single surface, because objects created in 3D editing software commonly contain multiple materials.
</description>
<methods>
<method name="add_morph_target">
@@ -17378,22 +17463,22 @@ returns:= "username=user&amp;password=pass"
Amount of weights/bone indices per vertex (always 4).
</constant>
<constant name="ARRAY_VERTEX" value="0">
- Vertex array (array of [Vector3]() vertices).
+ Vertex array (array of [Vector3] vertices).
</constant>
<constant name="ARRAY_NORMAL" value="1">
- Normal array (array of [Vector3]() normals).
+ Normal array (array of [Vector3] normals).
</constant>
<constant name="ARRAY_TANGENT" value="2">
Tangent array, array of groups of 4 floats. first 3 floats determine the tangent, and the last the binormal direction as -1 or 1.
</constant>
<constant name="ARRAY_COLOR" value="3">
- Vertex array (array of [Color]() colors).
+ Vertex array (array of [Color] colors).
</constant>
<constant name="ARRAY_TEX_UV" value="4">
- UV array (array of [Vector3]() UVs or float array of groups of 2 floats (u,v)).
+ UV array (array of [Vector3] UVs or float array of groups of 2 floats (u,v)).
</constant>
<constant name="ARRAY_TEX_UV2" value="5">
- Second UV array (array of [Vector3]() UVs or float array of groups of 2 floats (u,v)).
+ Second UV array (array of [Vector3] UVs or float array of groups of 2 floats (u,v)).
</constant>
<constant name="ARRAY_BONES" value="6">
Array of bone indices, as a float array. Each element in groups of 4 floats.
@@ -17756,10 +17841,10 @@ returns:= "username=user&amp;password=pass"
</class>
<class name="MeshInstance" inherits="GeometryInstance" category="Core">
<brief_description>
- Node that instances meshes into a [Scenario].
+ Node that instances meshes into a scenario.
</brief_description>
<description>
- MeshInstance is a [Node] that takes a [Mesh] resource and adds it to the current [Scenario] by creating an instance of it. This is the class most often used to get 3D geometry rendered and can be used to instance a sigle [Mesh] in many places. This allows to reuse geometry and save on resources. When a [Mesh] has to be instanced more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance] instead.
+ MeshInstance is a [Node] that takes a [Mesh] resource and adds it to the current scenario by creating an instance of it. This is the class most often used to get 3D geometry rendered and can be used to instance a single [Mesh] in many places. This allows to reuse geometry and save on resources. When a [Mesh] has to be instanced more than thousands of times at close proximity, consider using a [MultiMesh] in a [MultiMeshInstance] instead.
</description>
<methods>
<method name="set_mesh">
@@ -17907,11 +17992,12 @@ returns:= "username=user&amp;password=pass"
</class>
<class name="MultiMesh" inherits="Resource" category="Core">
<brief_description>
- Provides high perfomance mesh instancing.
+ Provides high performance mesh instancing.
</brief_description>
<description>
MultiMesh provides low level mesh instancing. If the amount of [Mesh] instances needed goes from hundreds to thousands (and most need to be visible at close proximity) creating such a large amount of [MeshInstance] nodes may affect performance by using too much CPU or video memory.
- For this case a MultiMesh becomes very useful, as it can draw thousands of instances with little API overhead.[br] As a drawback, if the instances are too far away of each other, performance may be reduced as every sigle instance will always rendered (they are spatially indexed as one, for the whole object).
+ For this case a MultiMesh becomes very useful, as it can draw thousands of instances with little API overhead.
+ As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always rendered (they are spatially indexed as one, for the whole object).
Since instances may have any behavior, the AABB used for visibility must be provided by the user, or generated with [method generate_aabb].
</description>
<methods>
@@ -17933,14 +18019,14 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="count" type="int">
</argument>
<description>
- Set the amount of instnces that is going to be drawn. Changing this number will erase all the existing instance transform and color data.
+ Set the amount of instances that is going to be drawn. Changing this number will erase all the existing instance transform and color data.
</description>
</method>
<method name="get_instance_count" qualifiers="const">
<return type="int">
</return>
<description>
- Return the amount of instnces that is going to be drawn.
+ Return the amount of instances that is going to be drawn.
</description>
</method>
<method name="set_instance_transform">
@@ -18007,7 +18093,7 @@ returns:= "username=user&amp;password=pass"
Node that instances a [MultiMesh].
</brief_description>
<description>
- MultiMeshInstance is a [Node] that takes a [MultiMesh] resource and adds it to the current [Scenario] by creating an instance of it (yes, this is an instance of instances).
+ MultiMeshInstance is a [Node] that takes a [MultiMesh] resource and adds it to the current scenario by creating an instance of it (yes, this is an instance of instances).
</description>
<methods>
<method name="set_multimesh">
@@ -18395,13 +18481,13 @@ returns:= "username=user&amp;password=pass"
</description>
<methods>
<method name="set_navigation_polygon">
- <argument index="0" name="navpoly" type="Object">
+ <argument index="0" name="navpoly" type="NavigationPolygon">
</argument>
<description>
</description>
</method>
<method name="get_navigation_polygon" qualifiers="const">
- <return type="Object">
+ <return type="NavigationPolygon">
</return>
<description>
</description>
@@ -18607,12 +18693,12 @@ returns:= "username=user&amp;password=pass"
<description>
Nodes can be set as children of other nodes, resulting in a tree arrangement. Any tree of nodes is called a "Scene".
Scenes can be saved to disk, and then instanced into other scenes. This allows for very high flexibility in the architecture and data model of the projects.
- [SceneMainLoop] contains the "active" tree of nodes, and a node becomes active (receinving NOTIFICATION_ENTER_SCENE) when added to that tree.
- A node can contain any number of nodes as a children (but there is only one tree root) with the requirement that no two childrens with the same name can exist.
+ [SceneTree] contains the "active" tree of nodes, and a node becomes active (receiving NOTIFICATION_ENTER_SCENE) when added to that tree.
+ A node can contain any number of nodes as a children (but there is only one tree root) with the requirement that no two children with the same name can exist.
Nodes can, optionally, be added to groups. This makes it easy to reach a number of nodes from the code (for example an "enemies" group).
Nodes can be set to "process" state, so they constantly receive a callback requesting them to process (do anything). Normal processing ([method _process]) happens as fast as possible and is dependent on the frame rate, so the processing time delta is variable. Fixed processing ([method _fixed_process]) happens a fixed amount of times per second (by default 60) and is useful to link itself to the physics.
Nodes can also process input events. When set, the [method _input] function will be called with every input that the program receives. Since this is usually too overkill (unless used for simple projects), an [method _unhandled_input] function is called when the input was not handled by anyone else (usually, GUI [Control] nodes).
- To keep track of the scene hieararchy (specially when instancing scenes into scenes) an "owner" can be set to a node. This keeps track of who instanced what. This is mostly useful when writing editors and tools, though.
+ To keep track of the scene hierarchy (specially when instancing scenes into scenes) an "owner" can be set to a node. This keeps track of who instanced what. This is mostly useful when writing editors and tools, though.
Finally, when a node is freed, it will free all its children nodes too.
</description>
<methods>
@@ -18732,7 +18818,7 @@ returns:= "username=user&amp;password=pass"
</argument>
<description>
Fetch a node. NodePath must be valid (or else error will occur) and can be either the path to child node, a relative path (from the current node to another node), or an absolute path to a node.
- Note: fetching absolute paths only works when the node is inside the scene tree (see [method is_inside_scene]). Examples. Assume your current node is Character and following tree:[br]
+ Note: fetching absolute paths only works when the node is inside the scene tree (see [method is_inside_tree]). Examples. Assume your current node is Character and following tree:[br]
root/
root/Character
root/Character/Sword
@@ -18812,7 +18898,7 @@ returns:= "username=user&amp;password=pass"
<return type="NodePath">
</return>
<description>
- Return the absolute path of the current node. This only works if the curent node is inside the scene tree (see [method is_inside_scene]).
+ Return the absolute path of the current node. This only works if the current node is inside the scene tree (see [method is_inside_tree]).
</description>
</method>
<method name="get_path_to" qualifiers="const">
@@ -18830,7 +18916,7 @@ returns:= "username=user&amp;password=pass"
<argument index="1" name="persistent" type="bool" default="false">
</argument>
<description>
- Add a node to a group. Groups are helpers to name and organize group of nodes, like for example: "Enemies", "Collectables", etc. A [Node] can be in any number of groups. Nodes can be assigned a group at any time, but will not be added to it until they are inside the scene tree (see [method is_inside_scene]).
+ Add a node to a group. Groups are helpers to name and organize group of nodes, like for example: "Enemies", "Collectables", etc. A [Node] can be in any number of groups. Nodes can be assigned a group at any time, but will not be added to it until they are inside the scene tree (see [method is_inside_tree]).
</description>
</method>
<method name="remove_from_group">
@@ -18854,7 +18940,7 @@ returns:= "username=user&amp;password=pass"
<argument index="1" name="to_pos" type="int">
</argument>
<description>
- Move a child node to a different position (order) amongst the other children. Since calls, signals, etc are performed by tree order, changing the order of chilren nodes may be useful.
+ Move a child node to a different position (order) amongst the other children. Since calls, signals, etc are performed by tree order, changing the order of children nodes may be useful.
</description>
</method>
<method name="get_groups" qualifiers="const">
@@ -18879,12 +18965,12 @@ returns:= "username=user&amp;password=pass"
<return type="Node">
</return>
<description>
- Get the node owner (see [method set_node_owner]).
+ Get the node owner (see [method set_owner]).
</description>
</method>
<method name="remove_and_skip">
<description>
- Remove a node and set all its children as childrens of the parent node (if exists). All even subscriptions that pass by the removed node will be unsubscribed.
+ Remove a node and set all its children as children of the parent node (if exists). All even subscriptions that pass by the removed node will be unsubscribed.
</description>
</method>
<method name="get_index" qualifiers="const">
@@ -18896,7 +18982,7 @@ returns:= "username=user&amp;password=pass"
</method>
<method name="print_tree">
<description>
- Print the screne to stdout. Used mainly for debugging purposes.
+ Print the scene to stdout. Used mainly for debugging purposes.
</description>
</method>
<method name="set_filename">
@@ -18917,21 +19003,21 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="what" type="int">
</argument>
<description>
- Notify the current node and all its chldren recursively by calling notification() in all of them.
+ Notify the current node and all its children recursively by calling notification() in all of them.
</description>
</method>
<method name="set_fixed_process">
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Enables or disables node fixed framerate processing. When a node is being processed, it will receive a NOTIFICATION_PROCESS at a fixed (usually 60fps, check [OS] to change that) interval (and the [method _fixed_process] callback will be called if exists). It is common to check how much time was elapsed since the previous frame by calling [method get_fixed_process_time].
+ Enables or disables node fixed framerate processing. When a node is being processed, it will receive a NOTIFICATION_PROCESS at a fixed (usually 60 fps, check [OS] to change that) interval (and the [method _fixed_process] callback will be called if exists). It is common to check how much time was elapsed since the previous frame by calling [method get_fixed_process_delta_time].
</description>
</method>
<method name="get_fixed_process_delta_time" qualifiers="const">
<return type="float">
</return>
<description>
- Return the time elapsed since the last fixed frame. This is always the same in fixed proecssing unless the frames per second is changed in [OS].
+ Return the time elapsed since the last fixed frame. This is always the same in fixed processing unless the frames per second is changed in [OS].
</description>
</method>
<method name="is_fixed_processing" qualifiers="const">
@@ -18945,7 +19031,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Enables or disables node processing. When a node is being processed, it will receive a NOTIFICATION_PROCESS on every drawn frame (and the [method _process] callback will be called if exists). It is common to check how much time was elapsed since the previous frame by calling [method get_process_time].
+ Enables or disables node processing. When a node is being processed, it will receive a NOTIFICATION_PROCESS on every drawn frame (and the [method _process] callback will be called if exists). It is common to check how much time was elapsed since the previous frame by calling [method get_process_delta_time].
</description>
</method>
<method name="get_process_delta_time" qualifiers="const">
@@ -18966,7 +19052,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Enable input processing for node. This is not requiered for GUI controls! It hooks up the node to receive all input (see [method _input]).
+ Enable input processing for node. This is not required for GUI controls! It hooks up the node to receive all input (see [method _input]).
</description>
</method>
<method name="is_processing_input" qualifiers="const">
@@ -18980,7 +19066,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Enable unhandled input processing for node. This is not requiered for GUI controls! It hooks up the node to receive all input that was not previously handled before (usually by a [Control]). (see [method _unhandled_input]).
+ Enable unhandled input processing for node. This is not required for GUI controls! It hooks up the node to receive all input that was not previously handled before (usually by a [Control]). (see [method _unhandled_input]).
</description>
</method>
<method name="is_processing_unhandled_input" qualifiers="const">
@@ -19131,7 +19217,7 @@ returns:= "username=user&amp;password=pass"
Base node for 2D system.
</brief_description>
<description>
- Base node for 2D system. Node2D contains a position, rotation and scale, which is used to position and animate. It can alternatively be used with a custom 2D transform ([Matrix32]). A tree of Node2Ds allows complex hierachies for animation and positioning.
+ Base node for 2D system. Node2D contains a position, rotation and scale, which is used to position and animate. It can alternatively be used with a custom 2D transform ([Matrix32]). A tree of Node2Ds allows complex hierarchies for animation and positioning.
</description>
<methods>
<method name="set_pos">
@@ -19299,10 +19385,12 @@ returns:= "username=user&amp;password=pass"
</class>
<class name="NodePath" category="Built-In Types">
<brief_description>
- Built-in type optimized for path traversing.
+ Pre-parsed scene tree path.
</brief_description>
<description>
- Built-in type optimized for path traversing. A Node path is an optimized compiled path used for traversing the scene tree. It references nodes and can reference properties in that node, or even reference properties inside the resources of the node.
+ A pre-parsed relative or absolute path in a scene tree, for use with [method Node.get_node] and similar functions. It can reference a node, a resource within a node, or a property of a node or resource. For instance, [code]"Path2D/PathFollow2D/Sprite:texture:size"[/code] would refer to the size property of the texture resource on the node named "Sprite" which is a child of the other named nodes in the path. Note that if you want to get a resource, you must end the path with a colon, otherwise the last element will be used as a property name.
+ You will usually just pass a string to [method Node.get_node] and it will be automatically converted, but you may occasionally want to parse a path ahead of time with [NodePath] or the literal syntax [code]@"path"[/code]. Exporting a [NodePath] variable will give you a node selection widget in the properties panel of the editor, which can often be useful.
+ A [NodePath] is made up of a list of node names, a list of "subnode" (resource) names, and the name of a property in the final node or resource.
</description>
<methods>
<method name="get_name">
@@ -19311,21 +19399,21 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return a path level name.
+ Get the node name indicated by [code]idx[/code] (0 to [method get_name_count])
</description>
</method>
<method name="get_name_count">
<return type="int">
</return>
<description>
- Return the path level count.
+ Get the number of node names which make up the path.
</description>
</method>
<method name="get_property">
<return type="String">
</return>
<description>
- Return the property associated (empty if none).
+ Get the path's property name, or an empty string if the path doesn't have a property.
</description>
</method>
<method name="get_subname">
@@ -19334,14 +19422,14 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return the subname level name.
+ Get the resource name indicated by [code]idx[/code] (0 to [method get_subname_count])
</description>
</method>
<method name="get_subname_count">
<return type="int">
</return>
<description>
- Return the subname count.
+ Get the number of resource names in the path.
</description>
</method>
<method name="is_absolute">
@@ -19364,6 +19452,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="from" type="String">
</argument>
<description>
+ Create a NodePath from a string, e.g. "Path2D/PathFollow2D/Sprite:texture:size". A path is absolute if it starts with a slash. Absolute paths are only valid in the global scene tree, not within individual scenes. In a relative path, [code]"."[/code] and [code]".."[/code] indicate the current node and its parent.
</description>
</method>
</methods>
@@ -19711,14 +19800,14 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="environment" type="String">
</argument>
<description>
- Return true if an envieronment variable exists.
+ Return true if an environment variable exists.
</description>
</method>
<method name="get_name" qualifiers="const">
<return type="String">
</return>
<description>
- Return the name of the host OS.
+ Return the name of the host OS. Possible values are: "Android", "BlackBerry 10", "Flash", "Haiku", "iOS", "HTML5", "OSX", "Server", "Windows", "WinRT", "X11"
</description>
</method>
<method name="get_cmdline_args">
@@ -19968,6 +20057,10 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="native_video_unpause">
+ <description>
+ </description>
+ </method>
<method name="get_scancode_string" qualifiers="const">
<return type="String">
</return>
@@ -20006,6 +20099,14 @@ returns:= "username=user&amp;password=pass"
<description>
</description>
</method>
+ <method name="set_thread_name">
+ <return type="int">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
<constant name="DAY_SUNDAY" value="0">
@@ -20085,8 +20186,8 @@ returns:= "username=user&amp;password=pass"
<description>
Base class for all non built-in types. Everything not a built-in type starts the inheritance chain from this class.
Objects do not manage memory, if inheriting from one the object will most likely have to be deleted manually (call the [method free] function from the script or delete from C++).
- Some derivates add memory management, such as [Reference] (which keps a reference count and deletes itself automatically when no longer referenced) and [Node], which deletes the children tree when deleted.
- Objects export properties, which are mainly useful for storage and editing, but not really so much in programming. Properties are exported in [method _get_property_list] and handled in [method _get] and [_set]. However, scripting languages and C++ have simper means to export them.
+ Some derivates add memory management, such as [Reference] (which keeps a reference count and deletes itself automatically when no longer referenced) and [Node], which deletes the children tree when deleted.
+ Objects export properties, which are mainly useful for storage and editing, but not really so much in programming. Properties are exported in [method _get_property_list] and handled in [method _get] and [method _set]. However, scripting languages and C++ have simpler means to export them.
Objects also receive notifications ([method _notification]). Notifications are a simple way to notify the object about simple events, so they can all be handled together.
</description>
<methods>
@@ -20101,7 +20202,7 @@ returns:= "username=user&amp;password=pass"
<return type="Array">
</return>
<description>
- Return the property list, array of dictionaries, dictionaries must countain: name:String, type:int (see TYPE_* enum in globals) and optionally: hint:int (see PROPERTY_HINT_* in globals), hint_string:String, usage:int (see PROPERTY_USAGE_* in globals).
+ Return the property list, array of dictionaries, dictionaries must contain: name:String, type:int (see TYPE_* enum in globals) and optionally: hint:int (see PROPERTY_HINT_* in globals), hint_string:String, usage:int (see PROPERTY_USAGE_* in globals).
</description>
</method>
<method name="_init" qualifiers="virtual">
@@ -20141,7 +20242,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="type" type="String">
</argument>
<description>
- Check the type of the obeject against a string (including inheritance).
+ Check the type of the object against a string (including inheritance).
</description>
</method>
<method name="set">
@@ -20164,7 +20265,7 @@ returns:= "username=user&amp;password=pass"
<return type="Array">
</return>
<description>
- Return the list of properties as an array of dictionaries, dictionaries countain: name:String, type:int (see TYPE_* enum in globals) and optionally: hint:int (see PROPERTY_HINT_* in globals), hint_string:String, usage:int (see PROPERTY_USAGE_* in globals).
+ Return the list of properties as an array of dictionaries, dictionaries contain: name:String, type:int (see TYPE_* enum in globals) and optionally: hint:int (see PROPERTY_HINT_* in globals), hint_string:String, usage:int (see PROPERTY_USAGE_* in globals).
</description>
</method>
<method name="get_method_list" qualifiers="const">
@@ -20209,7 +20310,7 @@ returns:= "username=user&amp;password=pass"
<argument index="1" name="value" type="var">
</argument>
<description>
- Set a metadata into the object. Medatada is serialized. Metadata can be [i]anything[/i].
+ Set a metadata into the object. Metadata is serialized. Metadata can be [i]anything[/i].
</description>
</method>
<method name="get_meta" qualifiers="const">
@@ -20232,7 +20333,7 @@ returns:= "username=user&amp;password=pass"
<return type="StringArray">
</return>
<description>
- Return the list of metadatas in the object.
+ Return the list of metadata in the object.
</description>
</method>
<method name="add_user_signal">
@@ -20522,7 +20623,7 @@ returns:= "username=user&amp;password=pass"
</class>
<class name="OmniLight" inherits="Light" category="Core">
<brief_description>
- OmniDirectional Light, such as a lightbulb or a candle.
+ OmniDirectional Light, such as a light bulb or a candle.
</brief_description>
<description>
An OmniDirectional light is a type of [Light] node that emits lights in all directions. The light is attenuated through the distance and this attenuation can be configured by changing the energy, radius and attenuation parameters of [Light]. TODO: Image of an omnilight.
@@ -20841,7 +20942,7 @@ returns:= "username=user&amp;password=pass"
<argument index="0" name="path" type="Node">
</argument>
<description>
- Pack will ignore any sub-nodes not owned by given node. See [Node.set_owner].
+ Pack will ignore any sub-nodes not owned by given node. See [method Node.set_owner].
</description>
</method>
<method name="instance" qualifiers="const">
@@ -20873,7 +20974,7 @@ returns:= "username=user&amp;password=pass"
Abstraction and base class for packet-based protocols.
</brief_description>
<description>
- PacketPeer is an abstration and base class for packet-based protocols (such as UDP). It provides an API for sending and receiving packets both as raw data or variables. This makes it easy to transfer data over a protocol, without having to encode data as low level bytes or having to worry about network ordering.
+ PacketPeer is an abstraction and base class for packet-based protocols (such as UDP). It provides an API for sending and receiving packets both as raw data or variables. This makes it easy to transfer data over a protocol, without having to encode data as low level bytes or having to worry about network ordering.
</description>
<methods>
<method name="get_var" qualifiers="const">
@@ -21006,7 +21107,7 @@ returns:= "username=user&amp;password=pass"
Provides an opaque background for [Control] children.
</brief_description>
<description>
- Panel is a [Control] that displays an opaque background. It's commoly used as a parent and container for other types of [Control] nodes. [center][img]images/panel_example.png[/img][/center]
+ Panel is a [Control] that displays an opaque background. It's commonly used as a parent and container for other types of [Control] nodes.
</description>
<methods>
</methods>
@@ -22226,7 +22327,7 @@ This method controls whether the position between two cached points is interpola
Singleton containing the list of remapped resources.
</brief_description>
<description>
- When exporting, the types of some resources may change internally so they are converted to more optimized versions. While it's not usually necesary to access to this directly (path remapping happens automatically when opeining a file), it's exported just for information.
+ When exporting, the types of some resources may change internally so they are converted to more optimized versions. While it's not usually necessary to access to this directly (path remapping happens automatically when opening a file), it's exported just for information.
</description>
<methods>
<method name="add_remap">
@@ -22614,11 +22715,11 @@ This method controls whether the position between two cached points is interpola
Intersect a ray in a given space, the returned object is a dictionary with the following fields:
position: place where ray is stopped.
normal: normal of the object at the point where the ray was stopped.
- shape: shape index of the object agaisnt which the ray was stopped.
- collider_: collider agaisnt which the ray was stopped.
- collider_id: collider id of the object agaisnt which the ray was stopped.
- collider: collider object agaisnt which the ray was stopped.
- rid: [RID] of the object agaisnt which the ray was stopped.
+ shape: shape index of the object against which the ray was stopped.
+ collider_: collider against which the ray was stopped.
+ collider_id: collider id of the object against which the ray was stopped.
+ collider: collider object against which the ray was stopped.
+ rid: [RID] of the object against which the ray was stopped.
If the ray did not intersect anything, then an empty dictionary (dir.empty()==true) is returned instead.
</description>
</method>
@@ -23811,7 +23912,7 @@ This method controls whether the position between two cached points is interpola
Base class for all objects affected by physics.
</brief_description>
<description>
- PhysicsBody2D is an abstract base class for implementing a physics body. All [i]x[/i]Body2D types inherit from it.
+ PhysicsBody2D is an abstract base class for implementing a physics body. All *Body2D types inherit from it.
</description>
<methods>
<method name="set_layer_mask">
@@ -23898,7 +23999,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="depth" type="float">
</argument>
<description>
- Set how far a body can go through this one, when it allows one-way collisions (see [method set_one_way_collision_detection]).
+ Set how far a body can go through this one, when it allows one-way collisions (see [method set_one_way_collision_direction]).
</description>
</method>
<method name="get_one_way_collision_max_depth" qualifiers="const">
@@ -25533,7 +25634,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="epsilon" type="float" default="0.00001">
</argument>
<description>
- Returns true if "point" is inside the plane (by a very minimum treshold).
+ Returns true if "point" is inside the plane (by a very minimum threshold).
</description>
</method>
<method name="intersect_3">
@@ -25882,14 +25983,14 @@ This method controls whether the position between two cached points is interpola
Base container control for popups and dialogs.
</brief_description>
<description>
- PopUp is a base [Control] used to show dialogs and popups. It's a subwindow and modal by default (see [Control]) and has helpers for custom popup behavior.
+ Popup is a base [Control] used to show dialogs and popups. It's a subwindow and modal by default (see [Control]) and has helpers for custom popup behavior.
</description>
<methods>
<method name="popup_centered">
<argument index="0" name="size" type="Vector2" default="Vector2(0,0)">
</argument>
<description>
- Popup (show the control in modal form) in the center of the screen, at the curent size, or at a size determined by "size".
+ Popup (show the control in modal form) in the center of the screen, at the current size, or at a size determined by "size".
</description>
</method>
<method name="popup_centered_ratio">
@@ -25970,7 +26071,7 @@ This method controls whether the position between two cached points is interpola
<argument index="3" name="accel" type="int" default="0">
</argument>
<description>
- Add a new item with text "label" and icon "texture". An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index.
+ Add a new item with text "label" and icon "texture". An id can optionally be provided, as well as an accelerator. If no id is provided, one will be created from the index.
</description>
</method>
<method name="add_item">
@@ -25981,7 +26082,7 @@ This method controls whether the position between two cached points is interpola
<argument index="2" name="accel" type="int" default="0">
</argument>
<description>
- Add a new item with text "label". An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index.
+ Add a new item with text "label". An id can optionally be provided, as well as an accelerator. If no id is provided, one will be created from the index.
</description>
</method>
<method name="add_icon_check_item">
@@ -25994,7 +26095,7 @@ This method controls whether the position between two cached points is interpola
<argument index="3" name="accel" type="int" default="0">
</argument>
<description>
- Add a new checkable item with text "label" and icon "texture". An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index. Note that checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually.
+ Add a new check able item with text "label" and icon "texture". An id can optionally be provided, as well as an accelerator. If no id is provided, one will be created from the index. Note that checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually.
</description>
</method>
<method name="add_check_item">
@@ -26005,7 +26106,7 @@ This method controls whether the position between two cached points is interpola
<argument index="2" name="accel" type="int" default="0">
</argument>
<description>
- Add a new checkable item with text "label". An id can optonally be provided, as well as an accelerator. If no id is provided, one will be created from the index. Note that checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually.
+ Add a new checkable item with text "label". An id can optionally be provided, as well as an accelerator. If no id is provided, one will be created from the index. Note that checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually.
</description>
</method>
<method name="add_submenu_item">
@@ -26281,35 +26382,35 @@ This method controls whether the position between two cached points is interpola
Portals provide virtual openings to rooms.
</brief_description>
<description>
- Portals provide virtual openings to [RoomInstance] nodes, so cameras can look at them from the outside. Note that portals are a visibility optimization technique, and are in no way related to the game of the same name (as in, they are not used for teleportation). For more information on how rooms and portals work, see [RoomInstance]. Portals are represented as 2D convex polygon shapes (in the X,Y local plane), and are placed on the surface of the areas occupied by a [RoomInstance], to indicate that the room can be accessed or looked-at through them. If two rooms are next to each other, and two similar portals in each of them share the same world position (and are parallel and opposed to each other), they will automatically "connect" and form "doors" (for example, the portals that connect a kitchen to a living room are placed in the door they share). Portals must always have a [RoomInstance] node as a parent, grandparent or far parent, or else they will not be active.
+ Portals provide virtual openings to [VisualInstance] nodes, so cameras can look at them from the outside. Note that portals are a visibility optimization technique, and are in no way related to the game of the same name (as in, they are not used for teleportation). For more information on how rooms and portals work, see [VisualInstance]. Portals are represented as 2D convex polygon shapes (in the X,Y local plane), and are placed on the surface of the areas occupied by a [VisualInstance], to indicate that the room can be accessed or looked-at through them. If two rooms are next to each other, and two similar portals in each of them share the same world position (and are parallel and opposed to each other), they will automatically "connect" and form "doors" (for example, the portals that connect a kitchen to a living room are placed in the door they share). Portals must always have a [VisualInstance] node as a parent, grandparent or far parent, or else they will not be active.
</description>
<methods>
<method name="set_shape">
<argument index="0" name="points" type="Vector2Array">
</argument>
<description>
- Set the portal shape. The shape is an array of [Point2] points, representing a convex polygon in the X,Y plane.
+ Set the portal shape. The shape is an array of [Vector2] points, representing a convex polygon in the X,Y plane.
</description>
</method>
<method name="get_shape" qualifiers="const">
<return type="Vector2Array">
</return>
<description>
- Return the portal shape. The shape is an array of [Point2] points, representing a convex polygon in the X,Y plane.
+ Return the portal shape. The shape is an array of [Vector2] points, representing a convex polygon in the X,Y plane.
</description>
</method>
<method name="set_enabled">
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Enable the portal (it is enabled by defaul though), disabling it will cause the parent [RoomInstance] to not be visible any longer when looking through the portal.
+ Enable the portal (it is enabled by default though), disabling it will cause the parent [VisualInstance] to not be visible any longer when looking through the portal.
</description>
</method>
<method name="is_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
- Return wether the portal is active. When disabled it causes the parent [RoomInstance] to not be visible any longer when looking through the portal.
+ Return whether the portal is active. When disabled it causes the parent [VisualInstance] to not be visible any longer when looking through the portal.
</description>
</method>
<method name="set_disable_distance">
@@ -26565,7 +26666,7 @@ This method controls whether the position between two cached points is interpola
<return type="Quat">
</return>
<description>
- Returns the inverse of the quaternion (applies to the inverse rotatio too).
+ Returns the inverse of the quaternion (applies to the inverse rotation too).
</description>
</method>
<method name="length">
@@ -27035,7 +27136,7 @@ This method controls whether the position between two cached points is interpola
<return type="Object">
</return>
<description>
- Return the closest object the ray is pointing to. Note that this does not consider the length of the vector, so you must also use [is_colliding] to check if the object returned is actually colliding with the ray.
+ Return the closest object the ray is pointing to. Note that this does not consider the length of the vector, so you must also use [method is_colliding] to check if the object returned is actually colliding with the ray.
</description>
</method>
<method name="get_collider_shape" qualifiers="const">
@@ -27139,7 +27240,7 @@ This method controls whether the position between two cached points is interpola
Ray 2D shape resource for physics.
</brief_description>
<description>
- Ray 2D shape resource for physics. A ray is not really a collision body, isntead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters.
+ Ray 2D shape resource for physics. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters.
</description>
<methods>
<method name="set_length">
@@ -27334,7 +27435,7 @@ This method controls whether the position between two cached points is interpola
Rectangle Shape for 2D Physics.
</brief_description>
<description>
- Rectangle Shape for 2D Physics. This shape is useful for modelling box-like 2D objects.
+ Rectangle Shape for 2D Physics. This shape is useful for modeling box-like 2D objects.
</description>
<methods>
<method name="set_extents">
@@ -27412,12 +27513,12 @@ This method controls whether the position between two cached points is interpola
Currently supported features:
Capturing [code]()[/code] and non-capturing [code](?:)[/code] groups
Any character [code].[/code]
- Shorthand caracter classes [code]\w \W \s \S \d \D[/code]
+ Shorthand character classes [code]\w \W \s \S \d \D[/code]
User-defined character classes such as [code][A-Za-z][/code]
Simple quantifiers [code]?[/code], [code]*[/code] and [code]+[/code]
Range quantifiers [code]{x,y}[/code]
Lazy (non-greedy) quantifiers [code]*?[/code]
- Begining [code]^[/code] and end [code]$[/code] anchors
+ Beginning [code]^[/code] and end [code]$[/code] anchors
Alternation [code]|[/code]
Backreferences [code]\1[/code] and [code]\g{1}[/code]
POSIX character classes [code][[:alnum:]][/code]
@@ -27478,6 +27579,14 @@ This method controls whether the position between two cached points is interpola
Returns a captured group. A captured group is the part of a string that matches a part of the pattern delimited by parentheses (unless they are non-capturing parentheses [i](?:)[/i]).
</description>
</method>
+ <method name="get_capture_start" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="capture" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_captures" qualifiers="const">
<return type="StringArray">
</return>
@@ -27526,7 +27635,7 @@ This method controls whether the position between two cached points is interpola
Base class for all resources.
</brief_description>
<description>
- Resource is the base class for all resource types. Resources are primarily data containers. They are reference counted and freed when no longer in use. They are also loaded only once from disk, and further attempts to load the resource will return the same reference (all this in contrast to a [Node], which is not reference counted and can be instanced from disk as many times as desred). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource.
+ Resource is the base class for all resource types. Resources are primarily data containers. They are reference counted and freed when no longer in use. They are also loaded only once from disk, and further attempts to load the resource will return the same reference (all this in contrast to a [Node], which is not reference counted and can be instanced from disk as many times as desired). Resources can be saved externally on disk or bundled into another object, such as a [Node] or another resource.
</description>
<methods>
<method name="set_path">
@@ -27697,7 +27806,7 @@ This method controls whether the position between two cached points is interpola
<return type="int">
</return>
<description>
- Poll the load. If OK is returned, this means poll will have to be called again. If ERR_EOF is returned, them the load has finished and the resource can be obtained by calling [get_resource].
+ Poll the load. If OK is returned, this means poll will have to be called again. If ERR_EOF is returned, them the load has finished and the resource can be obtained by calling [method get_resource].
</description>
</method>
<method name="wait">
@@ -27710,14 +27819,14 @@ This method controls whether the position between two cached points is interpola
<return type="int">
</return>
<description>
- Return the load stage. The total amount of stages can be queried with [get_stage_count]
+ Return the load stage. The total amount of stages can be queried with [method get_stage_count]
</description>
</method>
<method name="get_stage_count" qualifiers="const">
<return type="int">
</return>
<description>
- Return the total amount of stages (calls to [poll] ) needed to completely load this resource.
+ Return the total amount of stages (calls to [method poll]) needed to completely load this resource.
</description>
</method>
</methods>
@@ -27796,7 +27905,7 @@ This method controls whether the position between two cached points is interpola
Resource Preloader Node.
</brief_description>
<description>
- Resource Preloader Node. This node is used to preload sub-resources inside a scene, so when the scene is loaded all the resourcs are ready to use and be retrieved from here.
+ Resource Preloader Node. This node is used to preload sub-resources inside a scene, so when the scene is loaded all the resources are ready to use and be retrieved from here.
</description>
<methods>
<method name="add_resource">
@@ -28497,7 +28606,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="state" type="Physics2DDirectBodyState">
</argument>
<description>
- Override this function to use a custom force integrator. This allows to hook up to the physics processing and alter the simulation state for the object on every frame.
+ Called during physics processing, allowing you to read and safely modify the simulation state for the object. By default it works in addition to the usual physics behavior, but [method set_use_custom_integrator] allows you to disable the default behavior and do fully custom force integration for a body.
</description>
</method>
<method name="set_mode">
@@ -28588,7 +28697,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="linear_damp" type="float">
</argument>
<description>
- Set the linear damp for this body. If this value is different from -1, any linear damp derived from the world or areas will be overriden.
+ Set the linear damp for this body. If this value is different from -1, any linear damp derived from the world or areas will be overridden.
</description>
</method>
<method name="get_linear_damp" qualifiers="const">
@@ -28602,7 +28711,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="angular_damp" type="float">
</argument>
<description>
- Set the angular damp for this body. If this value is different from -1, any angular damp derived from the world or areas will be overriden.
+ Set the angular damp for this body. If this value is different from -1, any angular damp derived from the world or areas will be overridden.
</description>
</method>
<method name="get_angular_damp" qualifiers="const">
@@ -28616,7 +28725,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="linear_velocity" type="Vector2">
</argument>
<description>
- Set the body linear velocity. Can be used sporadically, but[b] DONT SET THIS IN EVERY FRAME [/b], because physics may be running in another thread and definitely runs at a different granularity. Use [_integrate_forces] as your process loop if you want to have precise control of the body state.
+ Set the body linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may be running in another thread and definitely runs at a different granularity. Use [method _integrate_forces] as your process loop if you want to have precise control of the body state.
</description>
</method>
<method name="get_linear_velocity" qualifiers="const">
@@ -28630,7 +28739,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="angular_velocity" type="float">
</argument>
<description>
- Set the body angular velocity. Can be used sporadically, but[b] DONT SET THIS IN EVERY FRAME [/b], because physics may be running in another thread and definitely runs at a different granularity. Use [_integrate_forces] as your process loop if you want to have precise control of the body state.
+ Set the body angular velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may be running in another thread and definitely runs at a different granularity. Use [method _integrate_forces] as your process loop if you want to have precise control of the body state.
</description>
</method>
<method name="get_angular_velocity" qualifiers="const">
@@ -28658,7 +28767,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set to true if the body shall not do any internal force integration at all (like gravity or air friction). Only the [method _integrate_forces] will be able to integrate them if overrided.
+ Pass true to disable the internal force integration (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined.
</description>
</method>
<method name="is_using_custom_integrator">
@@ -28687,7 +28796,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<description>
Set the continuous collision detection mode from the enum CCD_MODE_*.
- Coninuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. The first is more precise, and misses less impacts by small, fast-moving objects. The second is faster to compute, but can miss small, fat-moving objects.
+ Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. The first is more precise, and misses less impacts by small, fast-moving objects. The second is faster to compute, but can miss small, fat-moving objects.
</description>
</method>
<method name="get_continuous_collision_detection_mode" qualifiers="const">
@@ -28731,7 +28840,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="sleeping" type="bool">
</argument>
<description>
- Set whether a body is isleeping or not. Sleeping bodies are not affected by forces until a collision or an [method apply_impulse]/[method set_applied_force] wakes them up. Until then, they behave like a static body.
+ Set whether a body is sleeping or not. Sleeping bodies are not affected by forces until a collision or an [method apply_impulse] / [method set_applied_force] wakes them up. Until then, they behave like a static body.
</description>
</method>
<method name="is_sleeping" qualifiers="const">
@@ -28746,7 +28855,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<description>
Set the body ability to fall asleep when not moving. This saves an enormous amount of processor time when there are plenty of rigid bodies (non static) in a scene.
- Sleeping bodies are not affected by forces until a collision or an [method apply_impulse]/[method set_applied_force] wakes them up. Until then, they behave like a static body.
+ Sleeping bodies are not affected by forces until a collision or an [method apply_impulse] / [method set_applied_force] wakes them up. Until then, they behave like a static body.
</description>
</method>
<method name="is_able_to_sleep" qualifiers="const">
@@ -28850,7 +28959,7 @@ This method controls whether the position between two cached points is interpola
Room data resource.
</brief_description>
<description>
- Room contains the data to define the bounds of a scene (using a BSP Tree). It is instanced by a [RoomInstance] node to create rooms. See that class documentation for more information about rooms.
+ Room contains the data to define the bounds of a scene (using a BSP Tree). It is instanced by a [VisualInstance] node to create rooms. See that class documentation for more information about rooms.
</description>
<methods>
<method name="set_room">
@@ -29069,7 +29178,7 @@ This method controls whether the position between two cached points is interpola
Library that contains a collection of samples.
</brief_description>
<description>
- Library that contains a collection of [Sample]s, each identified by a text ID. This is used as a data container for the majority of the SamplePlayer classes and derivatives.
+ Library that contains a collection of [Sample], each identified by a text ID. This is used as a data container for the majority of the SamplePlayer classes and derivatives.
</description>
<methods>
<method name="add_sample">
@@ -30238,7 +30347,7 @@ This method controls whether the position between two cached points is interpola
</class>
<class name="ScrollContainer" inherits="Container" category="Core">
<brief_description>
- A helper node for displaying scollable elements (e.g. lists).
+ A helper node for displaying scrollable elements (e.g. lists).
</brief_description>
<description>
A ScrollContainer node with a [Control] child and scrollbar child ([HScrollbar], [VScrollBar], or both) will only draw the Control within the ScrollContainer area. Scrollbars will automatically be drawn at the right (for vertical) or bottom (for horizontal) and will enable dragging to move the viewable Control (and its children) within the ScrollContainer. Scrollbars will also automatically resize the grabber based on the minimum_size of the Control relative to the ScrollContainer. Works great with a [Panel] control.
@@ -30363,7 +30472,7 @@ This method controls whether the position between two cached points is interpola
Base class for separators.
</brief_description>
<description>
- Separator is a [Control] used for sepataring other controls. It's purely a visual decoration. Horizontal ([HSeparator]) and Vertical ([VSeparator]) versions are available.
+ Separator is a [Control] used for separating other controls. It's purely a visual decoration. Horizontal ([HSeparator]) and Vertical ([VSeparator]) versions are available.
</description>
<methods>
</methods>
@@ -31419,8 +31528,8 @@ This method controls whether the position between two cached points is interpola
<argument index="4" name="shape_motion" type="Vector2">
</argument>
<description>
- Return whether this shape would collide with another, if a given movemen was applied.
- This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test ont the other object ([code]shape_motion[/code]).
+ Return whether this shape would collide with another, if a given movement was applied.
+ This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test onto the other object ([code]shape_motion[/code]).
</description>
</method>
<method name="collide_and_get_contacts">
@@ -31452,7 +31561,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<description>
Return a list of the points where this shape would touch another, if a given movement was applied. If there are no collisions, the list is empty.
- This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test ont the other object ([code]shape_motion[/code]).
+ This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test onto the other object ([code]shape_motion[/code]).
</description>
</method>
</methods>
@@ -31464,7 +31573,7 @@ This method controls whether the position between two cached points is interpola
Skeleton for characters and animated objects.
</brief_description>
<description>
- Skeleton provides a hierachial interface for managing bones, including pose, rest and animation (see [Animation]). Skeleton will support rag doll dynamics in the future.
+ Skeleton provides a hierarchical interface for managing bones, including pose, rest and animation (see [Animation]). Skeleton will support rag doll dynamics in the future.
</description>
<methods>
<method name="add_bone">
@@ -32093,7 +32202,7 @@ This method controls whether the position between two cached points is interpola
</signals>
<constants>
<constant name="NOTIFICATION_TRANSFORM_CHANGED" value="29">
- Spatial nodes receive this notifacation with their global transform changes. This means that either the current or a parent node changed its transform.
+ Spatial nodes receive this notification with their global transform changes. This means that either the current or a parent node changed its transform.
</constant>
<constant name="NOTIFICATION_ENTER_WORLD" value="41">
</constant>
@@ -32638,7 +32747,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="flip_h" type="bool">
</argument>
<description>
- Set true to flip the sprite horizontaly.
+ Set true to flip the sprite horizontally.
</description>
</method>
<method name="is_flipped_h" qualifiers="const">
@@ -32715,7 +32824,7 @@ This method controls whether the position between two cached points is interpola
<return type="int">
</return>
<description>
- Return the amount of vertical frames. See [set_vframes].
+ Return the amount of vertical frames. See [method set_vframes].
</description>
</method>
<method name="set_hframes">
@@ -32729,7 +32838,7 @@ This method controls whether the position between two cached points is interpola
<return type="int">
</return>
<description>
- Return the amount of horizontal frames. See [set_hframes].
+ Return the amount of horizontal frames. See [method set_hframes].
</description>
</method>
<method name="set_modulate">
@@ -33188,7 +33297,7 @@ This method controls whether the position between two cached points is interpola
Abstraction and base class for stream-based protocols.
</brief_description>
<description>
- StreamPeer is an abstration and base class for stream-based protocols (such as TCP or Unix Sockets). It provides an API for sending and receiving data through streams as raw data or strings.
+ StreamPeer is an abstraction and base class for stream-based protocols (such as TCP or Unix Sockets). It provides an API for sending and receiving data through streams as raw data or strings.
</description>
<methods>
<method name="put_data">
@@ -33197,7 +33306,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="data" type="RawArray">
</argument>
<description>
- Send a chunk of data through the connection, blocking if necesary until the data is done sending. This function returns an [Error] code.
+ Send a chunk of data through the connection, blocking if necessary until the data is done sending. This function returns an Error code.
</description>
</method>
<method name="put_partial_data">
@@ -33206,7 +33315,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="data" type="RawArray">
</argument>
<description>
- Send a chunk of data through the connection, if all the data could not be sent at once, only part of it will. This function returns two values, an [Error] code and an integer, describing how much data was actually sent.
+ Send a chunk of data through the connection, if all the data could not be sent at once, only part of it will. This function returns two values, an Error code and an integer, describing how much data was actually sent.
</description>
</method>
<method name="get_data">
@@ -33215,7 +33324,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="bytes" type="int">
</argument>
<description>
- Return a chunk data with the received bytes. The amount of bytes to be received can be requested in the "bytes" argument. If not enough bytes are available, the function will block until the desired amount is received. This function returns two values, an [Error] code and a data array.
+ Return a chunk data with the received bytes. The amount of bytes to be received can be requested in the "bytes" argument. If not enough bytes are available, the function will block until the desired amount is received. This function returns two values, an Error code and a data array.
</description>
</method>
<method name="get_partial_data">
@@ -33224,7 +33333,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="bytes" type="int">
</argument>
<description>
- Return a chunk data with the received bytes. The amount of bytes to be received can be requested in the "bytes" argument. If not enough bytes are available, the function will return how many were actually received. This function returns two values, an [Error] code, and a data array.
+ Return a chunk data with the received bytes. The amount of bytes to be received can be requested in the "bytes" argument. If not enough bytes are available, the function will return how many were actually received. This function returns two values, an Error code, and a data array.
</description>
</method>
<method name="get_available_bytes" qualifiers="const">
@@ -33596,7 +33705,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="db" type="float">
</argument>
<description>
- Set the playback volume for this player, in decibels. This is a float between -80.0 (silent) and 0.0 (full volume). Values under -79.0 get truncated to -80, but values over 0.0 do not, so the warnings for overamplifying (see [set_volume]) still apply.
+ Set the playback volume for this player, in decibels. This is a float between -80.0 (silent) and 0.0 (full volume). Values under -79.0 get truncated to -80, but values over 0.0 do not, so the warnings for overamplifying (see [method set_volume]) still apply.
</description>
</method>
<method name="get_volume_db" qualifiers="const">
@@ -33700,7 +33809,7 @@ This method controls whether the position between two cached points is interpola
Built-in string class.
</brief_description>
<description>
- This is the built-in string class (and the one used by GDScript). It supports Unicode and provides all necesary means for string handling. Strings are reference counted and use a copy-on-write approach, so passing them around is cheap in resources.
+ This is the built-in string class (and the one used by GDScript). It supports Unicode and provides all necessary means for string handling. Strings are reference counted and use a copy-on-write approach, so passing them around is cheap in resources.
</description>
<methods>
<method name="basename">
@@ -33744,7 +33853,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="to" type="String">
</argument>
<description>
- Perform a case-sensitive comparison to antoher string, return -1 if less, 0 if equal and +1 if greater.
+ Perform a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
</description>
</method>
<method name="empty">
@@ -33769,7 +33878,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="from" type="int" default="0">
</argument>
<description>
- Find the first occurence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ Find the first occurrence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
</description>
</method>
<method name="find_last">
@@ -33778,7 +33887,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="what" type="String">
</argument>
<description>
- Find the last occurence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ Find the last occurrence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
</description>
</method>
<method name="findn">
@@ -33789,7 +33898,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="from" type="int" default="0">
</argument>
<description>
- Find the first occurence of a substring but search as case-insensitive, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ Find the first occurrence of a substring but search as case-insensitive, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
</description>
</method>
<method name="get_base_dir">
@@ -33937,7 +34046,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="to" type="String">
</argument>
<description>
- Perform a case-insensitive comparison to antoher string, return -1 if less, 0 if equal and +1 if greater.
+ Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
</description>
</method>
<method name="ord_at">
@@ -34015,7 +34124,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="from" type="int" default="-1">
</argument>
<description>
- Perform a search for a substring, but start from the end of the string instead of the begining.
+ Perform a search for a substring, but start from the end of the string instead of the beginning.
</description>
</method>
<method name="rfindn">
@@ -34026,7 +34135,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="from" type="int" default="-1">
</argument>
<description>
- Perform a search for a substring, but start from the end of the string instead of the begining. Also search case-insensitive.
+ Perform a search for a substring, but start from the end of the string instead of the beginning. Also search case-insensitive.
</description>
</method>
<method name="right">
@@ -34046,7 +34155,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
<description>
- Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
+ Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return \["One","Two","Three"\] if split by ",".
</description>
</method>
<method name="split_floats">
@@ -34057,14 +34166,14 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="allow_empty" type="bool" default="True">
</argument>
<description>
- Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",".
+ Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return \[1,2.5,3\] if split by ",".
</description>
</method>
<method name="strip_edges">
<return type="String">
</return>
<description>
- Return a copy of the string stripped of any non-printable character at the begining and the end.
+ Return a copy of the string stripped of any non-printable character at the beginning and the end.
</description>
</method>
<method name="substr">
@@ -34200,7 +34309,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="rect" type="Rect2">
</argument>
<description>
- Test a position in a rectangle, return wether it pases the mask test.
+ Test a position in a rectangle, return whether it passes the mask test.
</description>
</method>
<method name="set_default_margin">
@@ -34247,7 +34356,7 @@ This method controls whether the position between two cached points is interpola
<return type="Vector2">
</return>
<description>
- Return the "offset" of a stylebox, this is a helper function, like writing Point2( style.get_margin(MARGIN_LEFT), style.get_margin(MARGIN_TOP) )
+ Return the "offset" of a stylebox, this is a helper function, like writing [code]Vector2(style.get_margin(MARGIN_LEFT), style.get_margin(MARGIN_TOP))[/code].
</description>
</method>
<method name="draw" qualifiers="const">
@@ -34363,7 +34472,7 @@ This method controls whether the position between two cached points is interpola
Image mask based StyleBox, for mask test.
</brief_description>
<description>
- This StyleBox is similar to [StyleBoxTexture], but only meant to be used for mask testing. It takes an image and applies stretch rules to determine if the poit clicked is masked or not.
+ This StyleBox is similar to [StyleBoxTexture], but only meant to be used for mask testing. It takes an image and applies stretch rules to determine if the point clicked is masked or not.
</description>
<methods>
<method name="set_image">
@@ -34377,7 +34486,7 @@ This method controls whether the position between two cached points is interpola
<return type="Image">
</return>
<description>
- Return the image used for mask testing. (see [method set_imag]).
+ Return the image used for mask testing. (see [method set_image]).
</description>
</method>
<method name="set_expand">
@@ -34391,7 +34500,7 @@ This method controls whether the position between two cached points is interpola
<return type="bool">
</return>
<description>
- Return wether the expand property is set(default). When expanding, the image will use the same rules as [StyleBoxTexture] for expand. If not expanding, the image will always be tested at its original size.
+ Return whether the expand property is set(default). When expanding, the image will use the same rules as [StyleBoxTexture] for expand. If not expanding, the image will always be tested at its original size.
</description>
</method>
<method name="set_expand_margin_size">
@@ -34706,7 +34815,7 @@ This method controls whether the position between two cached points is interpola
<argument index="1" name="title" type="String">
</argument>
<description>
- Set a title for the tab. Tab titles are by default the children node name, but this can be overriden.
+ Set a title for the tab. Tab titles are by default the children node name, but this can be overridden.
</description>
</method>
<method name="get_tab_title" qualifiers="const">
@@ -34715,7 +34824,7 @@ This method controls whether the position between two cached points is interpola
<argument index="0" name="tab_idx" type="int">
</argument>
<description>
- Return the title for the tab. Tab titles are by default the children node name, but this can be overriden.
+ Return the title for the tab. Tab titles are by default the children node name, but this can be overridden.
</description>
</method>
<method name="set_tab_icon">
@@ -35259,7 +35368,7 @@ This method controls whether the position between two cached points is interpola
Match whole words when searching.
</constant>
<constant name="SEARCH_BACKWARDS" value="4">
- Search from end to begining.
+ Search from end to beginning.
</constant>
</constants>
<theme_items>
@@ -35312,7 +35421,7 @@ This method controls whether the position between two cached points is interpola
Texture for 2D and 3D.
</brief_description>
<description>
- A texture works by registering an image in the video hardware, which then can be used in 3D models or 2D [Sprite] or GUI [Control]s.
+ A texture works by registering an image in the video hardware, which then can be used in 3D models or 2D [Sprite] or GUI [Control].
</description>
<methods>
<method name="get_width" qualifiers="const">
@@ -35998,14 +36107,6 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="set_name">
- <return type="Error">
- </return>
- <argument index="0" name="name" type="String">
- </argument>
- <description>
- </description>
- </method>
</methods>
<constants>
<constant name="PRIORITY_LOW" value="0">
@@ -36301,6 +36402,15 @@ This method controls whether the position between two cached points is interpola
Return the tile index of the referenced cell.
</description>
</method>
+ <method name="get_cellv" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="pos" type="Vector2">
+ </argument>
+ <description>
+ Return the tile index of the cell referenced by a Vector2.
+ </description>
+ </method>
<method name="is_cell_x_flipped" qualifiers="const">
<return type="bool">
</return>
@@ -36323,6 +36433,17 @@ This method controls whether the position between two cached points is interpola
Return whether the referenced cell is flipped over the Y axis.
</description>
</method>
+ <method name="is_cell_transposed" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="x" type="int">
+ </argument>
+ <argument index="1" name="y" type="int">
+ </argument>
+ <description>
+ Return whether the referenced cell is transposed, i.e. the X and Y axes are swapped (mirroring with regard to the (1,1) vector).
+ </description>
+ </method>
<method name="clear">
<description>
Clear all cells.
@@ -37753,7 +37874,9 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="1" name="button" type="Texture">
</argument>
- <argument index="2" name="button_idx" type="int">
+ <argument index="2" name="button_idx" type="int" default="-1">
+ </argument>
+ <argument index="3" name="disabled" type="bool" default="false">
</argument>
<description>
</description>
@@ -37784,6 +37907,16 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="is_button_disabled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="column" type="int">
+ </argument>
+ <argument index="1" name="button_idx" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_tooltip">
<argument index="0" name="column" type="int">
</argument>
@@ -39297,7 +39430,7 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
- <method name="get_video_texutre">
+ <method name="get_video_texture">
<return type="Texture">
</return>
<description>
@@ -39412,7 +39545,7 @@ This method controls whether the position between two cached points is interpola
<return type="Rect2">
</return>
<description>
- Return the final, visuble rect in global screen coordinates.
+ Return the final, visible rect in global screen coordinates.
</description>
</method>
<method name="set_transparent_background">
@@ -39426,7 +39559,7 @@ This method controls whether the position between two cached points is interpola
<return type="bool">
</return>
<description>
- Reurn whether the viewport lets whatever is behind it to show.
+ Return whether the viewport lets whatever is behind it to show.
</description>
</method>
<method name="set_size_override">
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
new file mode 100644
index 0000000000..6311be767c
--- /dev/null
+++ b/doc/tools/makerst.py
@@ -0,0 +1,518 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import sys
+import xml.etree.ElementTree as ET
+
+input_list = []
+
+for arg in sys.argv[1:]:
+ input_list.append(arg)
+
+if len(input_list) < 1:
+ print 'usage: makerst.py <classes.xml>'
+ sys.exit(0)
+
+
+def validate_tag(elem, tag):
+ if elem.tag != tag:
+ print "Tag mismatch, expected '" + tag + "', got " + elem.tag
+ sys.exit(255)
+
+
+class_names = []
+classes = {}
+
+def ul_string(str,ul):
+ str+="\n"
+ for i in range(len(str)-1):
+ str+=ul
+ str+="\n"
+ return str
+
+def make_class_list(class_list, columns):
+
+ f = open('class_list.rst', 'wb')
+ prev = 0
+ col_max = len(class_list) / columns + 1
+ print ('col max is ', col_max)
+ col_count = 0
+ row_count = 0
+ last_initial = ''
+ fit_columns = []
+
+ for n in range(0, columns):
+ fit_columns += [[]]
+
+ indexers = []
+ last_initial = ''
+
+ idx = 0
+ for n in class_list:
+ col = idx / col_max
+ if col >= columns:
+ col = columns - 1
+ fit_columns[col] += [n]
+ idx += 1
+ if n[:1] != last_initial:
+ indexers += [n]
+ last_initial = n[:1]
+
+ row_max = 0
+ f.write("\n")
+
+ for n in range(0, columns):
+ if len(fit_columns[n]) > row_max:
+ row_max = len(fit_columns[n])
+
+ f.write("| ")
+ for n in range(0, columns):
+ f.write(" | |")
+
+ f.write("\n")
+ f.write("+")
+ for n in range(0, columns):
+ f.write("--+-------+")
+ f.write("\n")
+
+ for r in range(0, row_max):
+ s = '+ '
+ for c in range(0, columns):
+ if r >= len(fit_columns[c]):
+ continue
+
+ classname = fit_columns[c][r]
+ initial = classname[0]
+ if classname in indexers:
+ s += '**' + initial + '** | '
+ else:
+ s += ' | '
+
+ s += '[' + classname + '](class_'+ classname.lower()+') | '
+
+ s += '\n'
+ f.write(s)
+
+ for n in range(0, columns):
+ f.write("--+-------+")
+ f.write("\n")
+
+
+def rstize_text(text,cclass):
+
+ # Linebreak + tabs in the XML should become two line breaks unless in a "codeblock"
+ pos = 0
+ while True:
+ pos = text.find('\n', pos)
+ if pos == -1:
+ break
+
+ pre_text = text[:pos]
+ while text[pos+1] == '\t':
+ pos += 1
+ post_text = text[pos+1:]
+
+ # Handle codeblocks
+ if post_text.startswith("[codeblock]"):
+ end_pos = post_text.find("[/codeblock]")
+ if end_pos == -1:
+ sys.exit("ERROR! [codeblock] without a closing tag!")
+
+ code_text = post_text[len("[codeblock]"):end_pos]
+ post_text = post_text[end_pos:]
+
+ # Remove extraneous tabs
+ code_pos = 0
+ while True:
+ code_pos = code_text.find('\n', code_pos)
+ if code_pos == -1:
+ break
+
+ to_skip = 0
+ while code_pos+to_skip+1 < len(code_text) and code_text[code_pos+to_skip+1] == '\t':
+ to_skip += 1
+
+ if len(code_text[code_pos+to_skip+1:])==0:
+ code_text = code_text[:code_pos] + "\n"
+ code_pos += 1
+ else:
+ code_text = code_text[:code_pos] + "\n " + code_text[code_pos+to_skip+1:]
+ code_pos += 5 - to_skip
+
+ text = pre_text + "\n[codeblock]" + code_text + post_text
+ pos += len("\n[codeblock]" + code_text)
+
+ # Handle normal text
+ else:
+ text = pre_text + "\n\n" + post_text
+ pos += 2
+
+ # Escape * character to avoid interpreting it as emphasis
+ pos = 0
+ while True:
+ pos = text.find('*', pos)
+ if pos == -1:
+ break
+ text = text[:pos] + "\*" + text[pos + 1:]
+ pos += 2
+
+ # Escape _ character at the end of a word to avoid interpreting it as an inline hyperlink
+ pos = 0
+ while True:
+ pos = text.find('_', pos)
+ if pos == -1:
+ break
+ if not text[pos + 1].isalnum(): # don't escape within a snake_case word
+ text = text[:pos] + "\_" + text[pos + 1:]
+ pos += 2
+ else:
+ pos += 1
+
+ # Handle [tags]
+ pos = 0
+ while True:
+ pos = text.find('[', pos)
+ if pos == -1:
+ break
+
+ endq_pos = text.find(']', pos + 1)
+ if endq_pos == -1:
+ break
+
+ pre_text = text[:pos]
+ post_text = text[endq_pos + 1:]
+ tag_text = text[pos + 1:endq_pos]
+
+ if tag_text in class_names:
+ tag_text = make_type(tag_text)
+ else: # command
+ cmd = tag_text
+ space_pos = tag_text.find(' ')
+ if cmd.find('html') == 0:
+ cmd = tag_text[:space_pos]
+ param = tag_text[space_pos + 1:]
+ tag_text = param
+ elif cmd.find('method') == 0:
+ cmd = tag_text[:space_pos]
+ param = tag_text[space_pos + 1:]
+
+ if param.find('.') != -1:
+ (class_param, method_param) = param.split('.')
+ tag_text = ':ref:`'+class_param+'.'+method_param+'<class_' + class_param + '_' + method_param + '>`'
+ else:
+ tag_text = ':ref:`' + param + '<class_' + cclass +"_"+ param + '>`'
+ elif cmd.find('image=') == 0:
+ tag_text = "" #'![](' + cmd[6:] + ')'
+ elif cmd.find('url=') == 0:
+ tag_text = ':ref:`' + cmd[4:] + '<'+cmd[4:]+">`"
+ elif cmd == '/url':
+ tag_text = ')'
+ elif cmd == 'center':
+ tag_text = ''
+ elif cmd == '/center':
+ tag_text = ''
+ elif cmd == 'codeblock':
+ tag_text = '\n::\n'
+ elif cmd == '/codeblock':
+ tag_text = ''
+ # Strip newline if the tag was alone on one
+ if pre_text[-1] == '\n':
+ pre_text = pre_text[:-1]
+ elif cmd == 'br':
+ # Make a new paragraph instead of a linebreak, rst is not so linebreak friendly
+ tag_text = '\n\n'
+ # Strip potential leading spaces
+ while post_text[0] == ' ':
+ post_text = post_text[1:]
+ elif cmd == 'i' or cmd == '/i':
+ tag_text = '*'
+ elif cmd == 'b' or cmd == '/b':
+ tag_text = '**'
+ elif cmd == 'u' or cmd == '/u':
+ tag_text = ''
+ elif cmd == 'code' or cmd == '/code':
+ tag_text = '``'
+ else:
+ tag_text = ':ref:`' + tag_text + '<class_'+tag_text.lower()+'>`'
+
+ text = pre_text + tag_text + post_text
+ pos = len(pre_text) + len(tag_text)
+
+ # tnode = ET.SubElement(parent,"div")
+ # tnode.text=text
+
+ return text
+
+
+def make_type(t):
+ global class_names
+ if t in class_names:
+ return ':ref:`'+t+'<class_' + t.lower()+'>`'
+ return t
+
+
+def make_method(
+ f,
+ name,
+ m,
+ declare,
+ cname,
+ event=False,
+ pp=None
+ ):
+
+ if (declare or pp==None):
+ t = '- '
+ else:
+ t = ""
+
+ ret_type = 'void'
+ args = list(m)
+ mdata = {}
+ mdata['argidx'] = []
+ for a in args:
+ if a.tag == 'return':
+ idx = -1
+ elif a.tag == 'argument':
+ idx = int(a.attrib['index'])
+ else:
+ continue
+
+ mdata['argidx'].append(idx)
+ mdata[idx] = a
+
+ if not event:
+ if -1 in mdata['argidx']:
+ t += make_type(mdata[-1].attrib['type'])
+ else:
+ t += 'void'
+ t += ' '
+
+ if declare or pp==None:
+
+ # span.attrib["class"]="funcdecl"
+ # a=ET.SubElement(span,"a")
+ # a.attrib["name"]=name+"_"+m.attrib["name"]
+ # a.text=name+"::"+m.attrib["name"]
+
+ s = ' **'+m.attrib['name']+'** '
+ else:
+ s = ':ref:`'+ m.attrib['name']+'<class_' + cname+"_"+m.attrib['name'] + '>` '
+
+ s += ' **(**'
+ argfound = False
+ for a in mdata['argidx']:
+ arg = mdata[a]
+ if a < 0:
+ continue
+ if a > 0:
+ s += ', '
+ else:
+ s += ' '
+
+ s += make_type(arg.attrib['type'])
+ if 'name' in arg.attrib:
+ s += ' ' + arg.attrib['name']
+ else:
+ s += ' arg' + str(a)
+
+ if 'default' in arg.attrib:
+ s += '=' + arg.attrib['default']
+
+ argfound = True
+
+ if argfound:
+ s += ' '
+ s += ' **)**'
+
+ if 'qualifiers' in m.attrib:
+ s += ' ' + m.attrib['qualifiers']
+
+# f.write(s)
+ if (not declare):
+ if (pp!=None):
+ pp.append( (t,s) )
+ else:
+ f.write("- "+t+" "+s+"\n")
+ else:
+ f.write(t+s+"\n")
+
+
+def make_heading(title, underline):
+ return title + '\n' + underline*len(title) + "\n\n"
+
+
+
+def make_rst_class(node):
+
+ name = node.attrib['name']
+
+ f = open("class_"+name.lower() + '.rst', 'wb')
+
+ # Warn contributors not to edit this file directly
+ f.write(".. Generated automatically by doc/tools/makerst.py in Godot's source tree.\n")
+ f.write(".. DO NOT EDIT THIS FILE, but the doc/base/classes.xml source instead.\n\n")
+
+ f.write(".. _class_"+name+":\n\n")
+ f.write(make_heading(name, '='))
+
+ if 'inherits' in node.attrib:
+ inh = node.attrib['inherits'].strip()
+# whle inh in classes[cn]
+ f.write('**Inherits:** ')
+ first=True
+ while(inh in classes):
+ if (not first):
+ f.write(" **<** ")
+ else:
+ first=False
+
+ f.write(make_type(inh))
+ inode = classes[inh]
+ if ('inherits' in inode.attrib):
+ inh=inode.attrib['inherits'].strip()
+ else:
+ inh=None
+
+
+ f.write("\n\n")
+
+ inherited=[]
+ for cn in classes:
+ c=classes[cn]
+ if 'inherits' in c.attrib:
+ if (c.attrib['inherits'].strip()==name):
+ inherited.append(c.attrib['name'])
+
+ if (len(inherited)):
+ f.write('**Inherited By:** ')
+ for i in range(len(inherited)):
+ if (i>0):
+ f.write(", ")
+ f.write(make_type(inherited[i]))
+ f.write("\n\n")
+ if 'category' in node.attrib:
+ f.write('**Category:** ' + node.attrib['category'].strip() + "\n\n")
+
+ f.write(make_heading('Brief Description', '-'))
+ briefd = node.find('brief_description')
+ if briefd != None:
+ f.write(rstize_text(briefd.text.strip(),name) + "\n\n")
+
+ methods = node.find('methods')
+
+ if methods != None and len(list(methods)) > 0:
+ f.write(make_heading('Member Functions', '-'))
+ ml=[]
+ for m in list(methods):
+ make_method(f, node.attrib['name'], m, False,name,False,ml)
+ longest_t = 0
+ longest_s = 0
+ for s in ml:
+ sl = len(s[0])
+ if (sl>longest_s):
+ longest_s=sl
+ tl = len(s[1])
+ if (tl>longest_t):
+ longest_t=tl
+
+ sep="+"
+ for i in range(longest_s+2):
+ sep+="-"
+ sep+="+"
+ for i in range(longest_t+2):
+ sep+="-"
+ sep+="+\n"
+ f.write(sep)
+ for s in ml:
+ rt = s[0]
+ while( len(rt) < longest_s ):
+ rt+=" "
+ st = s[1]
+ while( len(st) < longest_t ):
+ st+=" "
+ f.write("| "+rt+" | "+st+" |\n")
+ f.write(sep)
+ f.write('\n')
+
+
+ events = node.find('signals')
+ if events != None and len(list(events)) > 0:
+ f.write(make_heading('Signals', '-'))
+ for m in list(events):
+ make_method(f, node.attrib['name'], m, True,name, True)
+ f.write('\n')
+
+ members = node.find('members')
+ if members != None and len(list(members)) > 0:
+ f.write(make_heading('Member Variables', '-'))
+
+ for c in list(members):
+ s = '- '
+ s += make_type(c.attrib['type']) + ' '
+ s += '**' + c.attrib['name'] + '**'
+ if c.text.strip() != '':
+ s += ' - ' + c.text.strip()
+ f.write(s + '\n')
+ f.write('\n')
+
+ constants = node.find('constants')
+ if constants != None and len(list(constants)) > 0:
+ f.write(make_heading('Numeric Constants', '-'))
+ for c in list(constants):
+ s = '- '
+ s += '**' + c.attrib['name'] + '**'
+ if 'value' in c.attrib:
+ s += ' = **' + c.attrib['value'] + '**'
+ if c.text.strip() != '':
+ s += ' --- ' + rstize_text(c.text.strip(),name)
+ f.write(s + '\n')
+ f.write('\n')
+
+ descr = node.find('description')
+ if descr != None and descr.text.strip() != '':
+ f.write(make_heading('Description', '-'))
+ f.write(rstize_text(descr.text.strip(),name) + "\n\n")
+
+ methods = node.find('methods')
+ if methods != None and len(list(methods)) > 0:
+ f.write(make_heading('Member Function Description', '-'))
+ for m in list(methods):
+ f.write(".. _class_"+name+"_"+m.attrib['name']+":\n\n")
+# f.write(ul_string(m.attrib['name'],"^"))
+ #f.write('\n<a name="'+m.attrib['name']+'">' + m.attrib['name'] + '</a>\n------\n')
+ make_method(f, node.attrib['name'], m, True,name)
+ f.write('\n')
+ d = m.find('description')
+ if d == None or d.text.strip() == '':
+ continue
+ f.write(rstize_text(d.text.strip(),name))
+ f.write("\n\n")
+ f.write('\n')
+
+
+for file in input_list:
+ tree = ET.parse(file)
+ doc = tree.getroot()
+
+ if 'version' not in doc.attrib:
+ print "Version missing from 'doc'"
+ sys.exit(255)
+
+ version = doc.attrib['version']
+
+ for c in list(doc):
+ if c.attrib['name'] in class_names:
+ continue
+ class_names.append(c.attrib['name'])
+ classes[c.attrib['name']] = c
+
+class_names.sort()
+
+#Don't make class list for Sphinx, :toctree: handles it
+#make_class_list(class_names, 2)
+
+for cn in class_names:
+ c = classes[cn]
+ make_rst_class(c)
+
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index e3a3e7def3..4b976c5b06 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -7088,11 +7088,13 @@ void RasterizerGLES2::_draw_tex_bg() {
copy_shader.set_uniform(CopyShaderGLES2::ENERGY,nrg);
copy_shader.set_uniform(CopyShaderGLES2::CUSTOM_ALPHA,float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]));
+ float flip_sign = (current_env->bg_mode==VS::ENV_BG_TEXTURE && current_rt && current_rt_vflip)?-1:1;
+
Vector3 vertices[4]={
- Vector3(-1,-1,1),
- Vector3( 1,-1,1),
- Vector3( 1, 1,1),
- Vector3(-1, 1,1)
+ Vector3(-1,-1*flip_sign,1),
+ Vector3( 1,-1*flip_sign,1),
+ Vector3( 1, 1*flip_sign,1),
+ Vector3(-1, 1*flip_sign,1)
};
@@ -7238,7 +7240,7 @@ void RasterizerGLES2::end_scene() {
bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR];
else
bgcolor = Globals::get_singleton()->get("render/default_clear_color");
- bgcolor = _convert_color(bgcolor);
+ bgcolor = _convert_color(bgcolor);
float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0;
glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a);
_glClearDepth(1.0);
diff --git a/drivers/nrex/regex.cpp b/drivers/nrex/regex.cpp
index 459cf28e1e..5d6c9583ef 100644
--- a/drivers/nrex/regex.cpp
+++ b/drivers/nrex/regex.cpp
@@ -21,6 +21,7 @@ void RegEx::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_valid"),&RegEx::is_valid);
ObjectTypeDB::bind_method(_MD("get_capture_count"),&RegEx::get_capture_count);
ObjectTypeDB::bind_method(_MD("get_capture","capture"),&RegEx::get_capture);
+ ObjectTypeDB::bind_method(_MD("get_capture_start","capture"),&RegEx::get_capture_start);
ObjectTypeDB::bind_method(_MD("get_captures"),&RegEx::_bind_get_captures);
};
@@ -68,6 +69,14 @@ String RegEx::get_capture(int capture) const {
}
+int RegEx::get_capture_start(int capture) const {
+
+ ERR_FAIL_COND_V( get_capture_count() <= capture, -1 );
+
+ return captures[capture].start;
+
+}
+
Error RegEx::compile(const String& p_pattern, int capture) {
clear();
diff --git a/drivers/nrex/regex.h b/drivers/nrex/regex.h
index ae8d40ceab..4b063f0bf1 100644
--- a/drivers/nrex/regex.h
+++ b/drivers/nrex/regex.h
@@ -35,6 +35,7 @@ public:
void clear();
bool is_valid() const;
int get_capture_count() const;
+ int get_capture_start(int capture) const;
String get_capture(int capture) const;
Error compile(const String& p_pattern, int capture = 9);
int find(const String& p_text, int p_start = 0, int p_end = -1) const;
diff --git a/drivers/register_driver_types.cpp b/drivers/register_driver_types.cpp
index e7bbf28f01..235438f126 100644
--- a/drivers/register_driver_types.cpp
+++ b/drivers/register_driver_types.cpp
@@ -31,7 +31,6 @@
#endif
#ifdef TOOLS_ENABLED
-#include "pe_bliss/pe_bliss_godot.h"
#include "platform/windows/export/export.h"
#endif
diff --git a/drivers/theora/video_stream_theora.cpp b/drivers/theora/video_stream_theora.cpp
index 1d2e6b9dda..e577c3f932 100644
--- a/drivers/theora/video_stream_theora.cpp
+++ b/drivers/theora/video_stream_theora.cpp
@@ -489,6 +489,9 @@ Ref<Texture> VideoStreamPlaybackTheora::get_texture() {
void VideoStreamPlaybackTheora::update(float p_delta) {
+ if (!file)
+ return;
+
if (!playing || paused) {
//printf("not playing\n");
return;
diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp
index 1a79272dc1..f89b55de12 100644
--- a/drivers/unix/memory_pool_static_malloc.cpp
+++ b/drivers/unix/memory_pool_static_malloc.cpp
@@ -48,7 +48,12 @@ void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) {
#else
- int total = p_bytes + DEFAULT_ALIGNMENT;
+ size_t total;
+ #if defined(_add_overflow)
+ if (_add_overflow(p_bytes, DEFAULT_ALIGNMENT, &total)) return NULL;
+ #else
+ total = p_bytes + DEFAULT_ALIGNMENT;
+ #endif
uint8_t* ptr = (uint8_t*)_alloc(total, p_description);
ERR_FAIL_COND_V( !ptr, ptr );
int ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
@@ -64,11 +69,18 @@ void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) {
MutexLock lock(mutex);
#ifdef DEBUG_MEMORY_ENABLED
- void *mem=malloc(p_bytes+sizeof(RingPtr)); /// add for size and ringlist
+
+ size_t total;
+ #if defined(_add_overflow)
+ if (_add_overflow(p_bytes, sizeof(RingPtr), &total)) return NULL;
+ #else
+ total = p_bytes + sizeof(RingPtr);
+ #endif
+ void *mem=malloc(total); /// add for size and ringlist
if (!mem) {
- printf("**ERROR: out of memory while allocating %i bytes by %s?\n",(int) p_bytes, p_description);
- printf("**ERROR: memory usage is %i\n", (int)get_total_usage());
+ printf("**ERROR: out of memory while allocating %lu bytes by %s?\n", (unsigned long) p_bytes, p_description);
+ printf("**ERROR: memory usage is %lu\n", (unsigned long) get_total_usage());
};
ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
@@ -129,7 +141,12 @@ void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) {
if (!p_memory)
return alloc(p_bytes);
- int total = p_bytes + DEFAULT_ALIGNMENT;
+ size_t total;
+ #if defined(_add_overflow)
+ if (_add_overflow(p_bytes, DEFAULT_ALIGNMENT, &total)) return NULL;
+ #else
+ total = p_bytes + DEFAULT_ALIGNMENT;
+ #endif
uint8_t* mem = (uint8_t*)p_memory;
int ofs = *(mem-1);
mem = mem - ofs;
@@ -321,7 +338,7 @@ size_t MemoryPoolStaticMalloc::get_max_usage() {
/* Most likely available only if memory debugger was compiled in */
int MemoryPoolStaticMalloc::get_alloc_count() {
- return 0;
+ return total_pointers;
}
void * MemoryPoolStaticMalloc::get_alloc_ptr(int p_alloc_idx) {
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index bd33c81298..6ace64a923 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -81,9 +81,9 @@ void ThreadPosix::wait_to_finish_func_posix(Thread* p_thread) {
tp->pthread=0;
}
-Error ThreadPosix::set_name(const String& p_name) {
+Error ThreadPosix::set_name_func_posix(const String& p_name) {
- ERR_FAIL_COND_V(pthread == 0, ERR_UNCONFIGURED);
+ pthread_t running_thread = pthread_self();
#ifdef PTHREAD_NO_RENAME
return ERR_UNAVAILABLE;
@@ -93,22 +93,15 @@ Error ThreadPosix::set_name(const String& p_name) {
#ifdef PTHREAD_RENAME_SELF
// check if thread is the same as caller
- int caller = Thread::get_caller_ID();
- int self = get_ID();
- if (caller != self) {
- ERR_EXPLAIN("On this platform, thread can only be renamed with calls from the threads to be renamed.");
- ERR_FAIL_V(ERR_UNAVAILABLE);
- return ERR_UNAVAILABLE;
- };
int err = pthread_setname_np(p_name.utf8().get_data());
#else
#ifdef PTHREAD_BSD_SET_NAME
- pthread_set_name_np(pthread, p_name.utf8().get_data());
+ pthread_set_name_np(running_thread, p_name.utf8().get_data());
int err = 0; // Open/FreeBSD ignore errors in this function
#else
- int err = pthread_setname_np(pthread, p_name.utf8().get_data());
+ int err = pthread_setname_np(running_thread, p_name.utf8().get_data());
#endif // PTHREAD_BSD_SET_NAME
#endif // PTHREAD_RENAME_SELF
@@ -123,7 +116,7 @@ void ThreadPosix::make_default() {
create_func=create_func_posix;
get_thread_ID_func=get_thread_ID_func_posix;
wait_to_finish_func=wait_to_finish_func_posix;
-
+ set_name_func = set_name_func_posix;
}
ThreadPosix::ThreadPosix() {
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index 179d56d5bd..06a17c2ae6 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -55,13 +55,14 @@ class ThreadPosix : public Thread {
static Thread* create_func_posix(ThreadCreateCallback p_callback,void *,const Settings&);
static ID get_thread_ID_func_posix();
static void wait_to_finish_func_posix(Thread* p_thread);
-
+
+ static Error set_name_func_posix(const String& p_name);
+
ThreadPosix();
public:
virtual ID get_ID() const;
- Error set_name(const String& p_name);
static void make_default();
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 676ac85ada..d2aed239cb 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -102,6 +102,18 @@ bool InputDefault::is_action_pressed(const StringName& p_action) {
if (joy_buttons_pressed.has(c))
return true;
} break;
+ case InputEvent::JOYSTICK_MOTION: {
+
+ const InputEventJoystickMotion &iejm=E->get().joy_motion;
+ int c = _combine_device(iejm.axis,device);
+ if (_joy_axis.has(c)) {
+ if (iejm.axis_value < 0) {
+ if (_joy_axis[c] < -0.5f) return true;
+ }
+ else
+ if (_joy_axis[c] > 0.5f) return true;
+ }
+ } break;
}
}
@@ -157,7 +169,7 @@ void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_
};
js.uid = uidname;
//printf("looking for mappings for guid %ls\n", uidname.c_str());
- int mapping = -1;
+ int mapping = fallback_mapping;
for (int i=0; i < map_db.size(); i++) {
if (js.uid == map_db[i].uid) {
mapping = i;
@@ -387,115 +399,134 @@ void InputDefault::set_mouse_in_window(bool p_in_window) {
static const char *s_ControllerMappings [] =
{
#ifdef WINDOWS_ENABLED
- "8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
- "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
- "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
- "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
- "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
- "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
- "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
- "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
- "4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
- "6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
- "36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,",
- "4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,",
- "00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,",
- "00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,",
- "28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,",
- "ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,",
- "8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
- "8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
- "10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,",
- "79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,",
- "4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,",
- "d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,",
- "a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,",
- "8f0e0300000000000000504944564944,Trust GTX 28,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,",
- "4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
- "6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
- "83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows,",
- "c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+ "00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "10080300000000000000504944564944,PS2 USB,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,",
+ "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
+ "28040140000000000000504944564944,GamePad Pro USB,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,",
+ "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "36280100000000000000504944564944,OUYA Controller,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,",
+ "4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,",
+ "4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+ "4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
+ "4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
"79000600000000000000504944564944,Generic Speedlink,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
+ "83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
+ "88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,",
+ "8f0e0300000000000000504944564944,Trust GXT 28,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "8f0e0d31000000000000504944564944,Multilaser JS071 USB,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "8f0e1200000000000000504944564944,Acme,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+ "d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "ff113133000000000000504944564944,SVEN X-PAD,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,",
+ "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"__XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
-
#endif
+
#ifdef OSX_ENABLED
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
- "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
- "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
- "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
- "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
+ "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,",
+ "0d0f0000000000004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
+ "4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
+ "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
+ "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
+ "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
+ "79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,",
+ "83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
+ "891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
+ "8f0e0000000000000300000000000000,Piranha xtreme,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
#endif
+
#if X11_ENABLED
- "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
- "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
- "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
- "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
- "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
- "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
- "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
- "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
- "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
- "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
- "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
- "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
- "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "030000000d0f00001000000011010000,HORI CO.,LTD. FIGHTING STICK 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7",
+ "030000000d0f00002200000011010000,HORI CO.,LTD. REAL ARCADE Pro.V3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,",
+ "030000000d0f00004d00000011010000,HORI Gem Pad 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,",
- "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
+ "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,",
+ "03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
+ "03000000280400000140000000010000,Gravis GamePad Pro USB ,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,",
+ "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
+ "030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,",
+ "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
+ "030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
+ "030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
- "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
- "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
+ "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
- "030000006d04000016c2000010010000,Logitech Logitech Dual Action,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
- "03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,",
+ "030000005e040000d102000001010000,Microsoft X-Box One pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,",
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,",
+ "030000006d04000016c2000010010000,Logitech Logitech Dual Action,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
- "05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,",
- "030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
- "030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,",
- "0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
- "0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
- "030000006f0e00001f01000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "03000000280400000140000000010000,Gravis GamePad Pro USB ,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,",
- "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "030000006f0e00001304000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
- "03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,",
+ "030000006f0e00001f01000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000006f0e00002801000011010000,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b0,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:h0.2,righttrigger:b7,b:b2,",
+ "030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "03000000790000001100000010010000,RetroLink Saturn Classic Controller,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
+ "03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,",
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
- "030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,",
+ "030000008916000001fd000024010000,Razer Onza Classic Edition,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,",
+ "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,",
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
+ "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
+ "03000000c9110000f055000011010000,HJC Game GAMEPAD,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b4,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+ "03000000fd0500002a26000000010000,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b5,rightshoulder:b7,rightx:a2,start:b11,righty:a3,dpleft:h0.8,lefttrigger:b8,x:b0,dpup:h0.1,back:b10,leftstick:b2,leftshoulder:b6,y:b1,a:b3,dpright:h0.2,righttrigger:b9,b:b4,",
+ "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,",
+ "05000000362800000100000002010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,",
+ "05000000362800000100000003010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,",
+ "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,",
+ "05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,",
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,",
- "03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,",
- "05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
- "05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
- "030000008916000001fd000024010000,Razer Onza Classic Edition,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "030000005e040000d102000001010000,Microsoft X-Box One pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
- "03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,",
- "050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,",
- "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
- "030000000d0f00002200000011010000,HORI CO.,LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,",
- "030000000d0f00001000000011010000,HORI CO.,LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7",
- "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
- "0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
- "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,",
+
#endif
#if defined(__ANDROID__)
+ "Default Android Gamepad,Default Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,back:b4,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,",
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
+ "484f524920434f2e2c4c544420205041,Hori Gem Pad 3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b6,rightshoulder:b18,rightx:a2,start:b16,righty:a3,dpleft:h0.8,lefttrigger:b9,x:b0,dpup:h0.1,back:b15,leftstick:b4,leftshoulder:b3,y:b2,a:b1,dpright:h0.2,righttrigger:b10,b:b17,",
#endif
#ifdef JAVASCRIPT_ENABLED
"Default HTML5 Gamepad, Default Mapping,leftx:a0,lefty:a1,dpdown:b13,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:b14,lefttrigger:a6,x:b2,dpup:b12,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:b15,righttrigger:a7,b:b1,",
+ "303435652d303238652d4d6963726f73,Wired X360 Controller,leftx:a0,lefty:a1,dpdown:a7,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:a6,lefttrigger:a2,x:b2,dpup:a7,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:a6,righttrigger:a5,b:b1,",
+ "303435652d303731392d58626f782033,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,",
"303534632d303236382d536f6e792050,PS3 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:b6,rightstick:b2,rightshoulder:b11,rightx:a2,start:b3,righty:a3,dpleft:b7,lefttrigger:b8,x:b15,dpup:b4,back:b0,leftstick:b1,leftshoulder:b10,y:b12,a:b14,dpright:b5,righttrigger:b9,b:b13,",
"303534632d303563342d536f6e792043,PS4 Controller USB/Linux,leftx:a0,lefty:a1,dpdown:a7,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,dpleft:a6,lefttrigger:a3,x:b0,dpup:a7,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:a6,righttrigger:a4,b:b2,",
"303534632d303563342d576972656c65,PS4 Controller USB/Win,leftx:a0,lefty:a1,dpdown:b15,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a5,lefttrigger:a3,x:b0,dpup:b14,dpleft:b16,dpright:b17,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,righttrigger:b7,b:b2,",
- "303435652d303238652d4d6963726f73,Wired X360 Controller,leftx:a0,lefty:a1,dpdown:a7,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:a6,lefttrigger:a2,x:b2,dpup:a7,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:a6,righttrigger:a5,b:b1,",
- "303435652d303731392d58626f782033,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,",
"c2a94d6963726f736f66742058626f78,Wireless X360 Controller,leftx:a0,lefty:a1,dpdown:b14,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:b11,lefttrigger:a2,x:b2,dpup:b13,back:b6,leftstick:b9,leftshoulder:b4,y:b3,a:b0,dpright:b12,righttrigger:a5,b:b1,",
#endif
NULL
@@ -523,6 +554,8 @@ InputDefault::InputDefault() {
hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT;
hat_map_default[HAT_LEFT].value = 0;
+ fallback_mapping = -1;
+
String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG");
if (env_mapping != "") {
@@ -863,6 +896,16 @@ void InputDefault::remove_joy_mapping(String p_guid) {
}
}
+void InputDefault::set_fallback_mapping(String p_guid) {
+
+ for (int i = 0; i < map_db.size(); i++) {
+ if (map_db[i].uid == p_guid) {
+ fallback_mapping = i;
+ return;
+ }
+ }
+}
+
//Defaults to simple implementation for platforms with a fixed gamepad layout, like consoles.
bool InputDefault::is_joy_known(int p_device) {
@@ -875,10 +918,10 @@ String InputDefault::get_joy_guid(int p_device) const {
//platforms that use the remapping system can override and call to these ones
bool InputDefault::is_joy_mapped(int p_device) {
- return joy_names[p_device].mapping != -1 ? true : false;
+ int mapping = joy_names[p_device].mapping;
+ return mapping != -1 ? (mapping != fallback_mapping) : false;
}
String InputDefault::get_joy_guid_remapped(int p_device) const {
return joy_names[p_device].uid;
}
-
diff --git a/main/input_default.h b/main/input_default.h
index a75865e0cb..2f98d279d6 100644
--- a/main/input_default.h
+++ b/main/input_default.h
@@ -18,7 +18,6 @@ class InputDefault : public Input {
MainLoop *main_loop;
bool emulate_touch;
-
struct SpeedTrack {
uint64_t last_tick;
@@ -36,7 +35,7 @@ class InputDefault : public Input {
struct Joystick {
StringName name;
StringName uid;
- bool last_buttons[JOY_BUTTON_MAX + 2]; //html5 needs support for 18 buttons to map some devices correctly
+ bool last_buttons[JOY_BUTTON_MAX + 19]; //apparently SDL specifies 35 possible buttons on android
float last_axis[JOY_AXIS_MAX];
float filter;
int last_hat;
@@ -50,7 +49,7 @@ class InputDefault : public Input {
last_axis[i] = 0.0f;
}
- for (int i = 0; i < JOY_BUTTON_MAX + 2; i++) {
+ for (int i = 0; i < JOY_BUTTON_MAX + 19; i++) {
last_buttons[i] = false;
}
@@ -62,6 +61,7 @@ class InputDefault : public Input {
SpeedTrack mouse_speed_track;
Map<int, Joystick> joy_names;
+ int fallback_mapping;
RES custom_cursor;
public:
enum HatMask {
@@ -169,7 +169,7 @@ public:
bool is_joy_mapped(int p_device);
String get_joy_guid_remapped(int p_device) const;
-
+ void set_fallback_mapping(String p_guid);
InputDefault();
};
diff --git a/main/main.cpp b/main/main.cpp
index 19fe037613..68c40a6f2b 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -726,8 +726,9 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
/* Determine Video Driver */
- if (audio_driver=="") // specified in engine.cfg
+ if (audio_driver=="") { // specified in engine.cfg
audio_driver=GLOBAL_DEF("audio/driver",OS::get_singleton()->get_audio_driver_name(0));
+ }
for (int i=0;i<OS::get_singleton()->get_video_driver_count();i++) {
@@ -758,7 +759,8 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
if (audio_driver_idx<0) {
OS::get_singleton()->alert( "Invalid Audio Driver: "+audio_driver );
- goto error;
+ audio_driver_idx = 0;
+ //goto error;
}
{
@@ -1319,6 +1321,7 @@ bool Main::start() {
}
}
}
+ OS::get_singleton()->set_context(OS::CONTEXT_EDITOR);
//editor_node->set_edited_scene(game);
} else {
@@ -1463,6 +1466,7 @@ bool Main::start() {
ProjectManager *pmanager = memnew( ProjectManager );
sml->get_root()->add_child(pmanager);
+ OS::get_singleton()->set_context(OS::CONTEXT_PROJECTMAN);
}
#endif
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index 126a8cd1eb..ff19518ad5 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -52,6 +52,7 @@ String GDScriptLanguage::get_template(const String& p_class_name, const String&
"# var a=2\n"+
"# var b=\"textvar\"\n\n"+
"func _ready():\n"+
+ "\t# Called every time the node is added to the scene.\n"+
"\t# Initialization here\n"+
"\tpass\n"+
"\n"+
@@ -285,6 +286,30 @@ void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const
p_functions->push_back(GDFunctions::get_info(GDFunctions::Function(i)));
}
+
+ //not really "functions", but..
+ {
+ MethodInfo mi;
+ mi.name="preload:Resource";
+ mi.arguments.push_back(PropertyInfo(Variant::STRING,"path"));
+ mi.return_val=PropertyInfo(Variant::OBJECT,"",PROPERTY_HINT_RESOURCE_TYPE,"Resource");
+ p_functions->push_back(mi);
+ }
+ {
+ MethodInfo mi;
+ mi.name="yield";
+ mi.arguments.push_back(PropertyInfo(Variant::OBJECT,"object"));
+ mi.arguments.push_back(PropertyInfo(Variant::STRING,"signal"));
+ mi.default_arguments.push_back(Variant::NIL);
+ mi.default_arguments.push_back(Variant::STRING);
+ p_functions->push_back(mi);
+ }
+ {
+ MethodInfo mi;
+ mi.name="assert";
+ mi.arguments.push_back(PropertyInfo(Variant::BOOL,"condition"));
+ p_functions->push_back(mi);
+ }
}
void GDScriptLanguage::get_public_constants(List<Pair<String,Variant> > *p_constants) const {
@@ -2300,8 +2325,8 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
"# Key",
"# MouseMotion",
"# MouseButton",
- "# JoyMotion",
- "# JoyButton",
+ "# JoystickMotion",
+ "# JoystickButton",
"# ScreenTouch",
"# ScreenDrag",
"# Action"
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 62c5eb735a..1b2ed670ad 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -2456,6 +2456,7 @@ void GDInstance::get_method_list(List<MethodInfo> *p_list) const {
MethodInfo mi;
mi.name=E->key();
+ mi.flags|=METHOD_FLAG_FROM_SCRIPT;
for(int i=0;i<E->get().get_argument_count();i++)
mi.arguments.push_back(PropertyInfo(Variant::NIL,"arg"+itos(i)));
p_list->push_back(mi);
@@ -2677,40 +2678,47 @@ void GDScriptLanguage::frame() {
void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
static const char *_reserved_words[]={
- "break",
- "class",
- "continue",
- "const",
- "else",
- "elif",
- "enum",
- "extends" ,
- "onready",
- "for" ,
- "func" ,
- "if" ,
- "in" ,
- "null" ,
- "not" ,
- "return" ,
- "self" ,
- "while" ,
- "true" ,
- "false" ,
- "tool",
- "var",
- "setget",
- "pass",
+ // operators
"and",
+ "in",
+ "not",
"or",
- "export",
+ // types and values
+ "false",
+ "float",
+ "int",
+ "null",
+ "PI",
+ "self",
+ "true",
+ // functions
"assert",
"breakpoint",
+ "class",
+ "extends",
+ "func",
+ "preload",
+ "setget",
+ "signal",
+ "tool",
"yield",
+ // var
+ "const",
+ "enum",
+ "export",
+ "onready",
"static",
- "float",
- "int",
- "signal",
+ "var",
+ // control flow
+ "break",
+ "continue",
+ "if",
+ "elif",
+ "else",
+ "for",
+ "pass",
+ "return",
+ "while",
0};
diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java
index aef6591864..7c5ac33c85 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java
@@ -54,6 +54,8 @@ public class GodotLib {
public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
public static native void joybutton(int p_device, int p_but, boolean p_pressed);
public static native void joyaxis(int p_device, int p_axis, float p_value);
+ public static native void joyhat(int p_device, int p_hat_x, int p_hat_y);
+ public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name);
public static native void focusin();
public static native void focusout();
public static native void audio();
diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index 492eb4cb54..e210161e8b 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -36,14 +36,21 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.content.ContextWrapper;
import android.view.InputDevice;
+import android.hardware.input.InputManager;
import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
+import org.godotengine.godot.input.InputManagerCompat;
+import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
/**
* A simple GLSurfaceView sub-class that demonstrate how to perform
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
@@ -62,7 +69,7 @@ import javax.microedition.khronos.opengles.GL10;
* that matches it exactly (with regards to red/green/blue/alpha channels
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
-public class GodotView extends GLSurfaceView {
+public class GodotView extends GLSurfaceView implements InputDeviceListener {
private static String TAG = "GodotView";
private static final boolean DEBUG = false;
@@ -75,6 +82,8 @@ public class GodotView extends GLSurfaceView {
private Godot activity;
+
+ private InputManagerCompat mInputManager;
public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, boolean p_use_32_bits, Godot p_activity) {
super(context);
ctx=context;
@@ -88,7 +97,8 @@ public class GodotView extends GLSurfaceView {
//will only work on SDK 11+!!
setPreserveEGLContextOnPause(true);
}
-
+ mInputManager = InputManagerCompat.Factory.getInputManager(this.getContext());
+ mInputManager.registerInputDeviceListener(this, null);
init(false, 16, 0);
}
@@ -119,50 +129,112 @@ public class GodotView extends GLSurfaceView {
button = 3;
break;
case KeyEvent.KEYCODE_BUTTON_L1:
- button = 4;
+ button = 9;
break;
case KeyEvent.KEYCODE_BUTTON_L2:
- button = 6;
+ button = 15;
break;
case KeyEvent.KEYCODE_BUTTON_R1:
- button = 5;
+ button = 10;
break;
case KeyEvent.KEYCODE_BUTTON_R2:
- button = 7;
+ button = 16;
break;
case KeyEvent.KEYCODE_BUTTON_SELECT:
- button = 10;
+ button = 4;
break;
case KeyEvent.KEYCODE_BUTTON_START:
- button = 11;
+ button = 6;
break;
case KeyEvent.KEYCODE_BUTTON_THUMBL:
- button = 8;
+ button = 7;
break;
case KeyEvent.KEYCODE_BUTTON_THUMBR:
- button = 9;
+ button = 8;
break;
case KeyEvent.KEYCODE_DPAD_UP:
- button = 12;
+ button = 11;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
- button = 13;
+ button = 12;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
- button = 14;
+ button = 13;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
- button = 15;
+ button = 14;
+ break;
+ case KeyEvent.KEYCODE_BUTTON_C:
+ button = 17;
+ break;
+ case KeyEvent.KEYCODE_BUTTON_Z:
+ button = 18;
break;
default:
- button = keyCode - KeyEvent.KEYCODE_BUTTON_1;
+ button = keyCode - KeyEvent.KEYCODE_BUTTON_1 + 20;
break;
};
-
return button;
};
+ private static class joystick {
+ public int device_id;
+ public String name;
+ public ArrayList<InputDevice.MotionRange> axes;
+ public ArrayList<InputDevice.MotionRange> hats;
+ }
+
+ private static class RangeComparator implements Comparator<InputDevice.MotionRange> {
+ @Override
+ public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
+ return arg0.getAxis() - arg1.getAxis();
+ }
+ }
+
+ ArrayList<joystick> joy_devices = new ArrayList<joystick>();
+
+ private int find_joy_device(int device_id) {
+ for (int i=0; i<joy_devices.size(); i++) {
+ if (joy_devices.get(i).device_id == device_id) {
+ return i;
+ }
+ }
+ onInputDeviceAdded(device_id);
+ return joy_devices.size() - 1;
+ }
+
+ @Override public void onInputDeviceAdded(int deviceId) {
+ joystick joy = new joystick();
+ joy.device_id = deviceId;
+ int id = joy_devices.size();
+ InputDevice device = mInputManager.getInputDevice(deviceId);
+ joy.name = device.getName();
+ joy.axes = new ArrayList<InputDevice.MotionRange>();
+ joy.hats = new ArrayList<InputDevice.MotionRange>();
+ List<InputDevice.MotionRange> ranges = device.getMotionRanges();
+ Collections.sort(ranges, new RangeComparator());
+ for (InputDevice.MotionRange range : ranges) {
+ if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
+ joy.hats.add(range);
+ }
+ else {
+ joy.axes.add(range);
+ }
+ }
+ joy_devices.add(joy);
+ GodotLib.joyconnectionchanged(id, true, joy.name);
+ }
+
+ @Override public void onInputDeviceRemoved(int deviceId) {
+ int id = find_joy_device(deviceId);
+ joy_devices.remove(id);
+ GodotLib.joyconnectionchanged(id, false, "");
+ }
+
+ @Override public void onInputDeviceChanged(int deviceId) {
+
+ }
@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
@@ -177,7 +249,7 @@ public class GodotView extends GLSurfaceView {
if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) {
int button = get_godot_button(keyCode);
- int device = event.getDeviceId();
+ int device = find_joy_device(event.getDeviceId());
GodotLib.joybutton(device, button, false);
return true;
@@ -209,7 +281,8 @@ public class GodotView extends GLSurfaceView {
if (event.getRepeatCount() > 0) // ignore key echo
return true;
int button = get_godot_button(keyCode);
- int device = event.getDeviceId();
+ int device = find_joy_device(event.getDeviceId());
+
//Log.e(TAG, String.format("joy button down! button %x, %d, device %d", keyCode, button, device));
GodotLib.joybutton(device, button, true);
@@ -221,125 +294,27 @@ public class GodotView extends GLSurfaceView {
return super.onKeyDown(keyCode, event);
}
- public float axis_value(MotionEvent p_event, InputDevice p_device, int p_axis, int p_pos) {
-
- final InputDevice.MotionRange range = p_device.getMotionRange(p_axis, p_event.getSource());
- if (range == null)
- return 0;
-
- //Log.e(TAG, String.format("axis ranges %f, %f, %f", range.getRange(), range.getMin(), range.getMax()));
-
- final float flat = range.getFlat();
- final float value =
- p_pos < 0 ? p_event.getAxisValue(p_axis):
- p_event.getHistoricalAxisValue(p_axis, p_pos);
-
- final float absval = Math.abs(value);
- if (absval <= flat) {
- return 0;
- };
-
- final float ret = (value - range.getMin()) / range.getRange() * 2 - 1.0f;
-
- return ret;
- };
-
- float[] last_axis_values = { 0, 0, 0, 0, -1, -1 };
- boolean[] last_axis_buttons = { false, false, false, false, false, false }; // dpad up down left right, ltrigger, rtrigger
-
- public void process_axis_state(MotionEvent p_event, int p_pos) {
-
- int device_id = p_event.getDeviceId();
- InputDevice device = p_event.getDevice();
- float val;
-
- val = axis_value(p_event, device, MotionEvent.AXIS_X, p_pos);
- if (val != last_axis_values[0]) {
- last_axis_values[0] = val;
- //Log.e(TAG, String.format("axis moved! axis %d, value %f", 0, val));
- GodotLib.joyaxis(device_id, 0, val);
- };
-
- val = axis_value(p_event, device, MotionEvent.AXIS_Y, p_pos);
- if (val != last_axis_values[1]) {
- last_axis_values[1] = val;
- //Log.e(TAG, String.format("axis moved! axis %d, value %f", 1, val));
- GodotLib.joyaxis(device_id, 1, val);
- };
-
- val = axis_value(p_event, device, MotionEvent.AXIS_Z, p_pos);
- if (val != last_axis_values[2]) {
- last_axis_values[2] = val;
- //Log.e(TAG, String.format("axis moved! axis %d, value %f", 2, val));
- GodotLib.joyaxis(device_id, 2, val);
- };
-
- val = axis_value(p_event, device, MotionEvent.AXIS_RZ, p_pos);
- if (val != last_axis_values[3]) {
- last_axis_values[3] = val;
- //Log.e(TAG, String.format("axis moved! axis %d, value %f", 3, val));
- GodotLib.joyaxis(device_id, 3, val);
- };
-
- val = axis_value(p_event, device, MotionEvent.AXIS_LTRIGGER, p_pos);
- if (val != last_axis_values[4]) {
- last_axis_values[4] = val;
- if ((val != 0) != (last_axis_buttons[4])) {
- last_axis_buttons[4] = (val != 0);
- GodotLib.joybutton(device_id, 6, (val != 0));
- };
- };
-
- val = axis_value(p_event, device, MotionEvent.AXIS_RTRIGGER, p_pos);
- if (val != last_axis_values[5]) {
- last_axis_values[5] = val;
- if ((val != 0) != (last_axis_buttons[5])) {
- last_axis_buttons[5] = (val != 0);
- GodotLib.joybutton(device_id, 7, (val != 0));
- };
- };
-
- val = axis_value(p_event, device, MotionEvent.AXIS_HAT_Y, p_pos);
-
- if (last_axis_buttons[0] != (val > 0)) {
- last_axis_buttons[0] = val > 0;
- GodotLib.joybutton(device_id, 12, val > 0);
- };
- if (last_axis_buttons[1] != (val < 0)) {
- last_axis_buttons[1] = val < 0;
- GodotLib.joybutton(device_id, 13, val > 0);
- };
-
- val = axis_value(p_event, device, MotionEvent.AXIS_HAT_X, p_pos);
- if (last_axis_buttons[2] != (val < 0)) {
- last_axis_buttons[2] = val < 0;
- GodotLib.joybutton(device_id, 14, val < 0);
- };
- if (last_axis_buttons[3] != (val > 0)) {
- last_axis_buttons[3] = val > 0;
- GodotLib.joybutton(device_id, 15, val > 0);
- };
- };
-
@Override public boolean onGenericMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
- // Process all historical movement samples in the batch
- final int historySize = event.getHistorySize();
+ int device_id = find_joy_device(event.getDeviceId());
+ joystick joy = joy_devices.get(device_id);
- // Process the movements starting from the
- // earliest historical position in the batch
- for (int i = 0; i < historySize; i++) {
- // Process the event at historical position i
- process_axis_state(event, i);
+ for (int i = 0; i < joy.axes.size(); i++) {
+ InputDevice.MotionRange range = joy.axes.get(i);
+ float value = (event.getAxisValue(range.getAxis()) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
+ //Log.e(TAG, String.format("axis event: %d, value %f", i, value));
+ GodotLib.joyaxis(device_id, i, value);
}
- // Process the current movement sample in the batch (position -1)
- process_axis_state(event, -1);
+ for (int i = 0; i < joy.hats.size(); i+=2) {
+ int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis()));
+ int hatY = Math.round(event.getAxisValue(joy.hats.get(i+1).getAxis()));
+ //Log.e(TAG, String.format("HAT EVENT %d, %d", hatX, hatY));
+ GodotLib.joyhat(device_id, hatX, hatY);
+ }
return true;
-
-
};
return super.onGenericMotionEvent(event);
@@ -413,12 +388,12 @@ public class GodotView extends GLSurfaceView {
/* Fallback if 32bit View is not supported*/
private static class FallbackConfigChooser extends ConfigChooser {
private ConfigChooser fallback;
-
+
public FallbackConfigChooser(int r, int g, int b, int a, int depth, int stencil, ConfigChooser fallback) {
super(r, g, b, a, depth, stencil);
this.fallback = fallback;
}
-
+
@Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
EGLConfig ec = super.chooseConfig(egl, display, configs);
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java b/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java
new file mode 100644
index 0000000000..4615d2fbb5
--- /dev/null
+++ b/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.godotengine.godot.input;
+
+import android.content.Context;
+import android.os.Build;
+import android.os.Handler;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+
+public interface InputManagerCompat {
+ /**
+ * Gets information about the input device with the specified id.
+ *
+ * @param id The device id
+ * @return The input device or null if not found
+ */
+ public InputDevice getInputDevice(int id);
+
+ /**
+ * Gets the ids of all input devices in the system.
+ *
+ * @return The input device ids.
+ */
+ public int[] getInputDeviceIds();
+
+ /**
+ * Registers an input device listener to receive notifications about when
+ * input devices are added, removed or changed.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or
+ * null if the listener should be invoked on the calling thread's
+ * looper.
+ */
+ public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
+ Handler handler);
+
+ /**
+ * Unregisters an input device listener.
+ *
+ * @param listener The listener to unregister.
+ */
+ public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
+
+ /*
+ * The following three calls are to simulate V16 behavior on pre-Jellybean
+ * devices. If you don't call them, your callback will never be called
+ * pre-API 16.
+ */
+
+ /**
+ * Pass the motion events to the InputManagerCompat. This is used to
+ * optimize for polling for controllers. If you do not pass these events in,
+ * polling will cause regular object creation.
+ *
+ * @param event the motion event from the app
+ */
+ public void onGenericMotionEvent(MotionEvent event);
+
+ /**
+ * Tell the V9 input manager that it should stop polling for disconnected
+ * devices. You can call this during onPause in your activity, although you
+ * might want to call it whenever your game is not active (or whenever you
+ * don't care about being notified of new input devices)
+ */
+ public void onPause();
+
+ /**
+ * Tell the V9 input manager that it should start polling for disconnected
+ * devices. You can call this during onResume in your activity, although you
+ * might want to call it less often (only when the gameplay is actually
+ * active)
+ */
+ public void onResume();
+
+ public interface InputDeviceListener {
+ /**
+ * Called whenever the input manager detects that a device has been
+ * added. This will only be called in the V9 version when a motion event
+ * is detected.
+ *
+ * @param deviceId The id of the input device that was added.
+ */
+ void onInputDeviceAdded(int deviceId);
+
+ /**
+ * Called whenever the properties of an input device have changed since
+ * they were last queried. This will not be called for the V9 version of
+ * the API.
+ *
+ * @param deviceId The id of the input device that changed.
+ */
+ void onInputDeviceChanged(int deviceId);
+
+ /**
+ * Called whenever the input manager detects that a device has been
+ * removed. For the V9 version, this can take some time depending on the
+ * poll rate.
+ *
+ * @param deviceId The id of the input device that was removed.
+ */
+ void onInputDeviceRemoved(int deviceId);
+ }
+
+ /**
+ * Use this to construct a compatible InputManager.
+ */
+ public static class Factory {
+
+ /**
+ * Constructs and returns a compatible InputManger
+ *
+ * @param context the Context that will be used to get the system
+ * service from
+ * @return a compatible implementation of InputManager
+ */
+ public static InputManagerCompat getInputManager(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ return new InputManagerV16(context);
+ } else {
+ return new InputManagerV9();
+ }
+ }
+ }
+}
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java b/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
new file mode 100644
index 0000000000..f05701f455
--- /dev/null
+++ b/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.godotengine.godot.input;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.os.Build;
+import android.os.Handler;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+public class InputManagerV16 implements InputManagerCompat {
+
+ private final InputManager mInputManager;
+ private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
+
+ public InputManagerV16(Context context) {
+ mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+ mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
+ }
+
+ @Override
+ public InputDevice getInputDevice(int id) {
+ return mInputManager.getInputDevice(id);
+ }
+
+ @Override
+ public int[] getInputDeviceIds() {
+ return mInputManager.getInputDeviceIds();
+ }
+
+ static class V16InputDeviceListener implements InputManager.InputDeviceListener {
+ final InputManagerCompat.InputDeviceListener mIDL;
+
+ public V16InputDeviceListener(InputDeviceListener idl) {
+ mIDL = idl;
+ }
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ mIDL.onInputDeviceAdded(deviceId);
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ mIDL.onInputDeviceChanged(deviceId);
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ mIDL.onInputDeviceRemoved(deviceId);
+ }
+
+ }
+
+ @Override
+ public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
+ V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
+ mInputManager.registerInputDeviceListener(v16Listener, handler);
+ mListeners.put(listener, v16Listener);
+ }
+
+ @Override
+ public void unregisterInputDeviceListener(InputDeviceListener listener) {
+ V16InputDeviceListener curListener = mListeners.remove(listener);
+ if (null != curListener)
+ {
+ mInputManager.unregisterInputDeviceListener(curListener);
+ }
+
+ }
+
+ @Override
+ public void onGenericMotionEvent(MotionEvent event) {
+ // unused in V16
+ }
+
+ @Override
+ public void onPause() {
+ // unused in V16
+ }
+
+ @Override
+ public void onResume() {
+ // unused in V16
+ }
+
+}
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java b/platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java
new file mode 100644
index 0000000000..0334c00997
--- /dev/null
+++ b/platform/android/java/src/org/godotengine/godot/input/InputManagerV9.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.godotengine.godot.input;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+
+public class InputManagerV9 implements InputManagerCompat {
+ private static final String LOG_TAG = "InputManagerV9";
+ private static final int MESSAGE_TEST_FOR_DISCONNECT = 101;
+ private static final long CHECK_ELAPSED_TIME = 3000L;
+
+ private static final int ON_DEVICE_ADDED = 0;
+ private static final int ON_DEVICE_CHANGED = 1;
+ private static final int ON_DEVICE_REMOVED = 2;
+
+ private final SparseArray<long[]> mDevices;
+ private final Map<InputDeviceListener, Handler> mListeners;
+ private final Handler mDefaultHandler;
+
+ private static class PollingMessageHandler extends Handler {
+ private final WeakReference<InputManagerV9> mInputManager;
+
+ PollingMessageHandler(InputManagerV9 im) {
+ mInputManager = new WeakReference<InputManagerV9>(im);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case MESSAGE_TEST_FOR_DISCONNECT:
+ InputManagerV9 imv = mInputManager.get();
+ if (null != imv) {
+ long time = SystemClock.elapsedRealtime();
+ int size = imv.mDevices.size();
+ for (int i = 0; i < size; i++) {
+ long[] lastContact = imv.mDevices.valueAt(i);
+ if (null != lastContact) {
+ if (time - lastContact[0] > CHECK_ELAPSED_TIME) {
+ // check to see if the device has been
+ // disconnected
+ int id = imv.mDevices.keyAt(i);
+ if (null == InputDevice.getDevice(id)) {
+ // disconnected!
+ imv.notifyListeners(ON_DEVICE_REMOVED, id);
+ imv.mDevices.remove(id);
+ } else {
+ lastContact[0] = time;
+ }
+ }
+ }
+ }
+ sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT,
+ CHECK_ELAPSED_TIME);
+ }
+ break;
+ }
+ }
+
+ }
+
+ public InputManagerV9() {
+ mDevices = new SparseArray<long[]>();
+ mListeners = new HashMap<InputDeviceListener, Handler>();
+ mDefaultHandler = new PollingMessageHandler(this);
+ // as a side-effect, populates our collection of watched
+ // input devices
+ getInputDeviceIds();
+ }
+
+ @Override
+ public InputDevice getInputDevice(int id) {
+ return InputDevice.getDevice(id);
+ }
+
+ @Override
+ public int[] getInputDeviceIds() {
+ // add any hitherto unknown devices to our
+ // collection of watched input devices
+ int[] activeDevices = InputDevice.getDeviceIds();
+ long time = SystemClock.elapsedRealtime();
+ for ( int id : activeDevices ) {
+ long[] lastContact = mDevices.get(id);
+ if ( null == lastContact ) {
+ // we have a new device
+ mDevices.put(id, new long[] { time });
+ }
+ }
+ return activeDevices;
+ }
+
+ @Override
+ public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
+ mListeners.remove(listener);
+ if (handler == null) {
+ handler = mDefaultHandler;
+ }
+ mListeners.put(listener, handler);
+ }
+
+ @Override
+ public void unregisterInputDeviceListener(InputDeviceListener listener) {
+ mListeners.remove(listener);
+ }
+
+ private void notifyListeners(int why, int deviceId) {
+ // the state of some device has changed
+ if (!mListeners.isEmpty()) {
+ // yes... this will cause an object to get created... hopefully
+ // it won't happen very often
+ for (InputDeviceListener listener : mListeners.keySet()) {
+ Handler handler = mListeners.get(listener);
+ DeviceEvent odc = DeviceEvent.getDeviceEvent(why, deviceId, listener);
+ handler.post(odc);
+ }
+ }
+ }
+
+ private static class DeviceEvent implements Runnable {
+ private int mMessageType;
+ private int mId;
+ private InputDeviceListener mListener;
+ private static Queue<DeviceEvent> sEventQueue = new ArrayDeque<DeviceEvent>();
+
+ private DeviceEvent() {
+ }
+
+ static DeviceEvent getDeviceEvent(int messageType, int id,
+ InputDeviceListener listener) {
+ DeviceEvent curChanged = sEventQueue.poll();
+ if (null == curChanged) {
+ curChanged = new DeviceEvent();
+ }
+ curChanged.mMessageType = messageType;
+ curChanged.mId = id;
+ curChanged.mListener = listener;
+ return curChanged;
+ }
+
+ @Override
+ public void run() {
+ switch (mMessageType) {
+ case ON_DEVICE_ADDED:
+ mListener.onInputDeviceAdded(mId);
+ break;
+ case ON_DEVICE_CHANGED:
+ mListener.onInputDeviceChanged(mId);
+ break;
+ case ON_DEVICE_REMOVED:
+ mListener.onInputDeviceRemoved(mId);
+ break;
+ default:
+ Log.e(LOG_TAG, "Unknown Message Type");
+ break;
+ }
+ // dump this runnable back in the queue
+ sEventQueue.offer(this);
+ }
+ }
+
+ @Override
+ public void onGenericMotionEvent(MotionEvent event) {
+ // detect new devices
+ int id = event.getDeviceId();
+ long[] timeArray = mDevices.get(id);
+ if (null == timeArray) {
+ notifyListeners(ON_DEVICE_ADDED, id);
+ timeArray = new long[1];
+ mDevices.put(id, timeArray);
+ }
+ long time = SystemClock.elapsedRealtime();
+ timeArray[0] = time;
+ }
+
+ @Override
+ public void onPause() {
+ mDefaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT);
+ }
+
+ @Override
+ public void onResume() {
+ mDefaultHandler.sendEmptyMessage(MESSAGE_TEST_FOR_DISCONNECT);
+ }
+
+}
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 75c1d78151..b5beb8fa2c 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -41,6 +41,7 @@
#include "core/os/keyboard.h"
#include "java_class_wrapper.h"
#include "android/asset_manager_jni.h"
+#include "main/input_default.h"
static JavaClassWrapper *java_class_wrapper=NULL;
static OS_Android *os_android=NULL;
@@ -639,6 +640,7 @@ struct JAndroidPointerEvent {
static List<JAndroidPointerEvent> pointer_events;
static List<InputEvent> key_events;
+static List<OS_Android::JoystickEvent> joy_events;
static bool initialized=false;
static Mutex *input_mutex=NULL;
static Mutex *suspend_mutex=NULL;
@@ -1067,6 +1069,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv * env, jo
key_events.pop_front();
};
+ while (joy_events.size()) {
+
+ OS_Android::JoystickEvent event = joy_events.front()->get();
+ os_android->process_joy_event(event);
+
+ joy_events.pop_front();
+ }
+
if (quit_request) {
os_android->main_loop_request_quit();
@@ -1380,48 +1390,57 @@ static unsigned int android_get_keysym(unsigned int p_code) {
return KEY_UNKNOWN;
}
-static int find_device(int p_device) {
-
- for (int i=0; i<joy_device_ids.size(); i++) {
-
- if (joy_device_ids[i] == p_device) {
- //print_line("found device at "+String::num(i));
- return i;
- };
- };
-
- //print_line("adding a device at" + String::num(joy_device_ids.size()));
- joy_device_ids.push_back(p_device);
-
- return joy_device_ids.size() - 1;
-};
-
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed) {
- InputEvent ievent;
- ievent.type = InputEvent::JOYSTICK_BUTTON;
- ievent.device = find_device(p_device);
- ievent.joy_button.button_index = p_button;
- ievent.joy_button.pressed = p_pressed;
+ OS_Android::JoystickEvent jevent;
+ jevent.device = p_device;
+ jevent.type = OS_Android::JOY_EVENT_BUTTON;
+ jevent.index = p_button;
+ jevent.pressed = p_pressed;
input_mutex->lock();
- key_events.push_back(ievent);
+ joy_events.push_back(jevent);
input_mutex->unlock();
};
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
- InputEvent ievent;
- ievent.type = InputEvent::JOYSTICK_MOTION;
- ievent.device = find_device(p_device);
- ievent.joy_motion.axis = p_axis;
- ievent.joy_motion.axis_value = p_value;
+ OS_Android::JoystickEvent jevent;
+ jevent.device = p_device;
+ jevent.type = OS_Android::JOY_EVENT_AXIS;
+ jevent.index = p_axis;
+ jevent.value = p_value;
input_mutex->lock();
- key_events.push_back(ievent);
+ joy_events.push_back(jevent);
input_mutex->unlock();
};
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv * env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y) {
+ OS_Android::JoystickEvent jevent;
+ jevent.device = p_device;
+ jevent.type = OS_Android::JOY_EVENT_HAT;
+ int hat = 0;
+ if (p_hat_x != 0) {
+ if (p_hat_x < 0) hat |= InputDefault::HAT_MASK_LEFT;
+ else hat |= InputDefault::HAT_MASK_RIGHT;
+ }
+ if (p_hat_y != 0) {
+ if (p_hat_y < 0) hat |= InputDefault::HAT_MASK_UP;
+ else hat |= InputDefault::HAT_MASK_DOWN;
+ }
+ jevent.hat = hat;
+ input_mutex->lock();
+ joy_events.push_back(jevent);
+ input_mutex->unlock();
+}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv * env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
+ if (os_android) {
+ String name = env->GetStringUTFChars( p_name, NULL );
+ os_android->joy_connection_changed(p_device, p_connected, name);
+ }
+}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h
index efa5b2839d..1d65d21251 100644
--- a/platform/android/java_glue.h
+++ b/platform/android/java_glue.h
@@ -45,6 +45,8 @@ extern "C" {
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv * env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y);
+ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv * env, jobject obj, jint p_device, jboolean p_connected, jstring p_name);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv * env, jobject obj);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv * env, jobject obj);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 03177317af..1751334c9b 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -178,7 +178,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
physics_2d_server->init();
input = memnew( InputDefault );
-
+ input->set_fallback_mapping("Default Android Gamepad");
}
void OS_Android::set_main_loop( MainLoop * p_main_loop ) {
@@ -370,6 +370,25 @@ void OS_Android::main_loop_focusin(){
}
+void OS_Android::process_joy_event(OS_Android::JoystickEvent p_event) {
+
+ switch (p_event.type) {
+ case JOY_EVENT_BUTTON:
+ last_id = input->joy_button(last_id, p_event.device, p_event.index, p_event.pressed);
+ break;
+ case JOY_EVENT_AXIS:
+ InputDefault::JoyAxis value;
+ value.min = -1;
+ value.value = p_event.value;
+ last_id = input->joy_axis(last_id, p_event.device, p_event.index, value);
+ break;
+ case JOY_EVENT_HAT:
+ last_id = input->joy_hat(last_id, p_event.device, p_event.hat);
+ break;
+ default:
+ return;
+ }
+}
void OS_Android::process_event(InputEvent p_event) {
@@ -742,6 +761,18 @@ void OS_Android::set_context_is_16_bits(bool p_is_16) {
rasterizer->set_force_16_bits_fbo(p_is_16);
}
+void OS_Android::joy_connection_changed(int p_device, bool p_connected, String p_name) {
+ return input->joy_connection_changed(p_device, p_connected, p_name, "");
+}
+
+bool OS_Android::is_joy_known(int p_device) {
+ return input->is_joy_mapped(p_device);
+}
+
+String OS_Android::get_joy_guid(int p_device) const {
+ return input->get_joy_guid_remapped(p_device);
+}
+
OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, bool p_use_apk_expansion) {
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 1ae42e9cc7..5075e766bc 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -83,6 +83,22 @@ public:
Point2 pos;
};
+ enum {
+ JOY_EVENT_BUTTON = 0,
+ JOY_EVENT_AXIS = 1,
+ JOY_EVENT_HAT = 2
+ };
+
+ struct JoystickEvent {
+
+ int device;
+ int type;
+ int index;
+ bool pressed;
+ float value;
+ int hat;
+ };
+
private:
Vector<TouchPos> touch;
@@ -224,6 +240,7 @@ public:
void process_accelerometer(const Vector3& p_accelerometer);
void process_touch(int p_what,int p_pointer, const Vector<TouchPos>& p_points);
+ void process_joy_event(JoystickEvent p_event);
void process_event(InputEvent p_event);
void init_video_mode(int p_video_width,int p_video_height);
@@ -232,6 +249,10 @@ public:
virtual void native_video_pause();
virtual void native_video_stop();
+ virtual bool is_joy_known(int p_device);
+ virtual String get_joy_guid(int p_device) const;
+ void joy_connection_changed(int p_device, bool p_connected, String p_name);
+
OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, bool p_use_apk_expansion);
~OS_Android();
diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp
index d2a350cf83..58ea26b8c9 100644
--- a/platform/bb10/os_bb10.cpp
+++ b/platform/bb10/os_bb10.cpp
@@ -29,7 +29,6 @@
#include "os_bb10.h"
#include "drivers/gles2/rasterizer_gles2.h"
-#include "drivers/gles1/rasterizer_gles1.h"
#include "servers/visual/visual_server_raster.h"
#include "core/os/dir_access.h"
@@ -605,6 +604,9 @@ String OSBB10::get_data_dir() const {
return data_dir;
};
+Size2 OSBB10::get_window_size() const {
+ return Vector2(default_videomode.width, default_videomode.height);
+}
OSBB10::OSBB10() {
diff --git a/platform/bb10/os_bb10.h b/platform/bb10/os_bb10.h
index a0481d1190..4ee5af8323 100644
--- a/platform/bb10/os_bb10.h
+++ b/platform/bb10/os_bb10.h
@@ -32,6 +32,7 @@
#include "os/input.h"
#include "drivers/unix/os_unix.h"
#include "os/main_loop.h"
+#include "main/input_default.h"
#include "servers/physics/physics_server_sw.h"
#include "servers/spatial_sound/spatial_sound_server_sw.h"
#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
@@ -135,6 +136,7 @@ public:
virtual VideoMode get_video_mode(int p_screen=0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const;
+ virtual Size2 get_window_size() const;
virtual String get_name();
virtual MainLoop *get_main_loop() const;
diff --git a/platform/haiku/key_mapping_haiku.cpp b/platform/haiku/key_mapping_haiku.cpp
index d7bde9a727..1c0584523a 100644
--- a/platform/haiku/key_mapping_haiku.cpp
+++ b/platform/haiku/key_mapping_haiku.cpp
@@ -160,7 +160,7 @@ unsigned int KeyMappingHaiku::get_keysym(int32 raw_char, int32 key) {
if (raw_char == B_UP_ARROW && key == 0x38) { return KEY_KP_8; }
if (raw_char == B_PAGE_UP && key == 0x39) { return KEY_KP_9; }
if (raw_char == 0x2F && key == 0x23) { return KEY_KP_DIVIDE; }
- if (raw_char == 0x2D && key == 0x25) { return KEY_KP_SUBSTRACT; }
+ if (raw_char == 0x2D && key == 0x25) { return KEY_KP_SUBTRACT; }
if (raw_char == B_DELETE && key == 0x65) { return KEY_KP_PERIOD; }
if (raw_char == 0x10) {
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index 88361e87e4..94fbb9e174 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -58,6 +58,7 @@ void _show_keyboard(String);
void _hide_keyboard();
bool _play_video(String, float, String, String);
bool _is_video_playing();
+void _pause_video();
void _focus_out_video();
void _unpause_video();
void _stop_video();
@@ -74,64 +75,30 @@ void _hide_keyboard() {
keyboard_text = "";
};
-/*
-bool _play_video(String p_path, float p_volume) {
-
- float player_volume = p_volume * AudioServer::get_singleton()->get_singleton()->get_stream_global_volume_scale();
- video_previous_volume = [[MPMusicPlayerController applicationMusicPlayer] volume];
-
- //[[MPMusicPlayerController applicationMusicPlayer] setVolume: player_volume];
-
- p_path = Globals::get_singleton()->globalize_path(p_path);
-
- NSString* file_path = [[[NSString alloc] initWithUTF8String:p_path.utf8().get_data()] autorelease];
- NSURL *file_url = [NSURL fileURLWithPath:file_path];
-
- _instance.moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:file_url];
- _instance.moviePlayerController.controlStyle = MPMovieControlStyleNone;
- [_instance.moviePlayerController setScalingMode:MPMovieScalingModeAspectFit];
- //[_instance.moviePlayerController setScalingMode:MPMovieScalingModeAspectFill];
-
- [[NSNotificationCenter defaultCenter] addObserver:_instance
- selector:@selector(moviePlayBackDidFinish:)
- name:MPMoviePlayerPlaybackDidFinishNotification
- object:_instance.moviePlayerController];
-
- [_instance.moviePlayerController.view setFrame:_instance.bounds];
- _instance.moviePlayerController.view.userInteractionEnabled = NO;
- [_instance addSubview:_instance.moviePlayerController.view];
- [_instance.moviePlayerController play];
-
- video_playing = true;
-
- return true;
-}
-*/
-
bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {
p_path = Globals::get_singleton()->globalize_path(p_path);
NSString* file_path = [[[NSString alloc] initWithUTF8String:p_path.utf8().get_data()] autorelease];
- //NSURL *file_url = [NSURL fileURLWithPath:file_path];
_instance.avAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:file_path]];
+
_instance.avPlayerItem =[[AVPlayerItem alloc]initWithAsset:_instance.avAsset];
[_instance.avPlayerItem addObserver:_instance forKeyPath:@"status" options:0 context:nil];
- _instance.avPlayer = [[AVPlayer alloc]initWithPlayerItem:_instance.avPlayerItem];
- _instance.avPlayerLayer =[AVPlayerLayer playerLayerWithPlayer:_instance.avPlayer];
+ _instance.avPlayer = [[AVPlayer alloc]initWithPlayerItem:_instance.avPlayerItem];
+ _instance.avPlayerLayer =[AVPlayerLayer playerLayerWithPlayer:_instance.avPlayer];
- [_instance.avPlayer addObserver:_instance forKeyPath:@"status" options:0 context:nil];
- [[NSNotificationCenter defaultCenter] addObserver:_instance
+ [_instance.avPlayer addObserver:_instance forKeyPath:@"status" options:0 context:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:_instance
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[_instance.avPlayer currentItem]];
[_instance.avPlayer addObserver:_instance forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:0];
- [_instance.avPlayerLayer setFrame:_instance.bounds];
- [_instance.layer addSublayer:_instance.avPlayerLayer];
- [_instance.avPlayer play];
+ [_instance.avPlayerLayer setFrame:_instance.bounds];
+ [_instance.layer addSublayer:_instance.avPlayerLayer];
+ [_instance.avPlayer play];
AVMediaSelectionGroup *audioGroup = [_instance.avAsset mediaSelectionGroupForMediaCharacteristic: AVMediaCharacteristicAudible];
@@ -173,23 +140,19 @@ bool _play_video(String p_path, float p_volume, String p_audio_track, String p_s
}
}
- video_playing = true;
+ video_playing = true;
return true;
}
bool _is_video_playing() {
- //NSInteger playback_state = _instance.moviePlayerController.playbackState;
- //return video_playing || _instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying;
- //if (video_found_error)
- // return false;
- //return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying);
-
- return video_playing || (_instance.avPlayer.rate > 0 && !_instance.avPlayer.error);
+ if (_instance.avPlayer.error) {
+ printf("Error during playback\n");
+ }
+ return (_instance.avPlayer.rate > 0 && !_instance.avPlayer.error);
}
void _pause_video() {
- //[_instance.moviePlayerController pause];
video_current_time = _instance.avPlayer.currentTime;
[_instance.avPlayer pause];
video_playing = false;
@@ -204,15 +167,9 @@ void _unpause_video() {
[_instance.avPlayer play];
video_playing = true;
-
- //video_current_time = kCMTimeZero;
};
void _stop_video() {
- //[_instance.moviePlayerController stop];
- //[_instance.moviePlayerController.view removeFromSuperview];
- //[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
-
[_instance.avPlayer pause];
[_instance.avPlayerLayer removeFromSuperlayer];
_instance.avPlayer = nil;
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index ec62cb5c26..9f6b8433aa 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -41,6 +41,7 @@
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
+#include "core/io/file_access_pack.h"
#include "core/globals.h"
#include "sem_iphone.h"
@@ -517,12 +518,25 @@ extern void _focus_out_video();
Error OSIPhone::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {
FileAccess* f = FileAccess::open(p_path, FileAccess::READ);
bool exists = f && f->is_open();
- printf("file exists for %ls, %i, %p\n", p_path.c_str(), (int)exists, f);
- if (f)
- memdelete(f);
+
+ String tempFile = get_data_dir();
if (!exists)
return FAILED;
- if ( _play_video(p_path, p_volume, p_audio_track, p_subtitle_track) )
+
+ if (p_path.begins_with("res://")) {
+ if (PackedData::get_singleton()->has_path(p_path)) {
+ print("Unable to play %S using the native player as it resides in a .pck file\n", p_path.c_str());
+ return ERR_INVALID_PARAMETER;
+ } else {
+ p_path = p_path.replace("res:/", Globals::get_singleton()->get_resource_path());
+ }
+ } else if (p_path.begins_with("user://"))
+ p_path = p_path.replace("user:/", get_data_dir());
+
+ memdelete(f);
+
+ print("Playing video: %S\n", p_path.c_str());
+ if (_play_video(p_path, p_volume, p_audio_track, p_subtitle_track) )
return OK;
return FAILED;
}
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index abe797fed1..d34e8bfe95 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -195,12 +195,12 @@ public:
void set_unique_ID(String p_ID);
String get_unique_ID() const;
- virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
- virtual bool native_video_is_playing() const;
- virtual void native_video_pause();
+ virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
+ virtual bool native_video_is_playing() const;
+ virtual void native_video_pause();
virtual void native_video_unpause();
virtual void native_video_focus_out();
- virtual void native_video_stop();
+ virtual void native_video_stop();
OSIPhone(int width, int height);
~OSIPhone();
diff --git a/platform/iphone/xcode/godot_xcode/data.pck b/platform/iphone/xcode/godot_xcode/data.pck
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/data.pck
diff --git a/platform/iphone/xcode/godot_xcode/godot_debug.iphone b/platform/iphone/xcode/godot_xcode/godot_debug.iphone
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_debug.iphone
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj b/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..bdba8488c8
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -0,0 +1,370 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D07CD43F1C5D573600B7FB28 /* Default-568h@2x~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4331C5D573600B7FB28 /* Default-568h@2x~iphone.png */; };
+ D07CD4401C5D573600B7FB28 /* Default-667h.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4341C5D573600B7FB28 /* Default-667h.png */; };
+ D07CD4411C5D573600B7FB28 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */; };
+ D07CD4421C5D573600B7FB28 /* Default-736h.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4361C5D573600B7FB28 /* Default-736h.png */; };
+ D07CD4431C5D573600B7FB28 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4371C5D573600B7FB28 /* Default-736h@3x.png */; };
+ D07CD4441C5D573600B7FB28 /* Default-Landscape-736h.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4381C5D573600B7FB28 /* Default-Landscape-736h.png */; };
+ D07CD4451C5D573600B7FB28 /* Default-Landscape@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4391C5D573600B7FB28 /* Default-Landscape@2x~ipad.png */; };
+ D07CD4461C5D573600B7FB28 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43A1C5D573600B7FB28 /* Default-Landscape~ipad.png */; };
+ D07CD4471C5D573600B7FB28 /* Default-Portrait@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x~ipad.png */; };
+ D07CD4481C5D573600B7FB28 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43C1C5D573600B7FB28 /* Default-Portrait~ipad.png */; };
+ D07CD4491C5D573600B7FB28 /* Default@2x~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43D1C5D573600B7FB28 /* Default@2x~iphone.png */; };
+ D07CD44A1C5D573600B7FB28 /* Default~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43E1C5D573600B7FB28 /* Default~iphone.png */; };
+ D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D07CD44D1C5D589C00B7FB28 /* Images.xcassets */; };
+ D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */; };
+ D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */; };
+ D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */; };
+ D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */; };
+ D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */; };
+ D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; };
+ D0BCFE7818AEBFEB004A7AAE /* data.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* data.pck */; };
+ D0BCFE7A18AEC06A004A7AAE /* godot_opt.iphone in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ D07CD4331C5D573600B7FB28 /* Default-568h@2x~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x~iphone.png"; sourceTree = "<group>"; };
+ D07CD4341C5D573600B7FB28 /* Default-667h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h.png"; sourceTree = "<group>"; };
+ D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = "<group>"; };
+ D07CD4361C5D573600B7FB28 /* Default-736h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h.png"; sourceTree = "<group>"; };
+ D07CD4371C5D573600B7FB28 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = "<group>"; };
+ D07CD4381C5D573600B7FB28 /* Default-Landscape-736h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape-736h.png"; sourceTree = "<group>"; };
+ D07CD4391C5D573600B7FB28 /* Default-Landscape@2x~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape@2x~ipad.png"; sourceTree = "<group>"; };
+ D07CD43A1C5D573600B7FB28 /* Default-Landscape~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape~ipad.png"; sourceTree = "<group>"; };
+ D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait@2x~ipad.png"; sourceTree = "<group>"; };
+ D07CD43C1C5D573600B7FB28 /* Default-Portrait~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait~ipad.png"; sourceTree = "<group>"; };
+ D07CD43D1C5D573600B7FB28 /* Default@2x~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x~iphone.png"; sourceTree = "<group>"; };
+ D07CD43E1C5D573600B7FB28 /* Default~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default~iphone.png"; sourceTree = "<group>"; };
+ D07CD44D1C5D589C00B7FB28 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
+ D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = godot_ios.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
+ D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
+ D0BCFE4318AEBDA2004A7AAE /* godot_ios-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "godot_ios-Info.plist"; sourceTree = "<group>"; };
+ D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ D0BCFE4918AEBDA2004A7AAE /* godot_ios-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "godot_ios-Prefix.pch"; sourceTree = "<group>"; };
+ D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ D0BCFE7718AEBFEB004A7AAE /* data.pck */ = {isa = PBXFileReference; lastKnownFileType = text; path = data.pck; sourceTree = "<group>"; };
+ D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = godot_opt.iphone; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D0BCFE3118AEBDA2004A7AAE /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */,
+ D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */,
+ D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */,
+ D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */,
+ D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ D0BCFE2B18AEBDA2004A7AAE = {
+ isa = PBXGroup;
+ children = (
+ D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */,
+ D0BCFE7718AEBFEB004A7AAE /* data.pck */,
+ D0BCFE4118AEBDA2004A7AAE /* godot_ios */,
+ D0BCFE3618AEBDA2004A7AAE /* Frameworks */,
+ D0BCFE3518AEBDA2004A7AAE /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ D0BCFE3518AEBDA2004A7AAE /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */,
+ D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */,
+ D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */,
+ D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */,
+ D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */,
+ D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ D0BCFE4118AEBDA2004A7AAE /* godot_ios */ = {
+ isa = PBXGroup;
+ children = (
+ D07CD4331C5D573600B7FB28 /* Default-568h@2x~iphone.png */,
+ D07CD4341C5D573600B7FB28 /* Default-667h.png */,
+ D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */,
+ D07CD4361C5D573600B7FB28 /* Default-736h.png */,
+ D07CD4371C5D573600B7FB28 /* Default-736h@3x.png */,
+ D07CD4381C5D573600B7FB28 /* Default-Landscape-736h.png */,
+ D07CD4391C5D573600B7FB28 /* Default-Landscape@2x~ipad.png */,
+ D07CD43A1C5D573600B7FB28 /* Default-Landscape~ipad.png */,
+ D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x~ipad.png */,
+ D07CD43C1C5D573600B7FB28 /* Default-Portrait~ipad.png */,
+ D07CD43D1C5D573600B7FB28 /* Default@2x~iphone.png */,
+ D07CD43E1C5D573600B7FB28 /* Default~iphone.png */,
+ D07CD44D1C5D589C00B7FB28 /* Images.xcassets */,
+ D0BCFE4218AEBDA2004A7AAE /* Supporting Files */,
+ );
+ path = godot_ios;
+ sourceTree = "<group>";
+ };
+ D0BCFE4218AEBDA2004A7AAE /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ D0BCFE4318AEBDA2004A7AAE /* godot_ios-Info.plist */,
+ D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */,
+ D0BCFE4918AEBDA2004A7AAE /* godot_ios-Prefix.pch */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ D0BCFE3318AEBDA2004A7AAE /* godot_ios */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_ios" */;
+ buildPhases = (
+ D0BCFE3018AEBDA2004A7AAE /* Sources */,
+ D0BCFE3118AEBDA2004A7AAE /* Frameworks */,
+ D0BCFE3218AEBDA2004A7AAE /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = godot_ios;
+ productName = godot_ios;
+ productReference = D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ D0BCFE2C18AEBDA2004A7AAE /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0500;
+ ORGANIZATIONNAME = GodotEngine;
+ };
+ buildConfigurationList = D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "godot_ios" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = D0BCFE2B18AEBDA2004A7AAE;
+ productRefGroup = D0BCFE3518AEBDA2004A7AAE /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D0BCFE3318AEBDA2004A7AAE /* godot_ios */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ D0BCFE3218AEBDA2004A7AAE /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D07CD4471C5D573600B7FB28 /* Default-Portrait@2x~ipad.png in Resources */,
+ D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */,
+ D0BCFE7818AEBFEB004A7AAE /* data.pck in Resources */,
+ D07CD4461C5D573600B7FB28 /* Default-Landscape~ipad.png in Resources */,
+ D07CD4411C5D573600B7FB28 /* Default-667h@2x.png in Resources */,
+ D07CD4401C5D573600B7FB28 /* Default-667h.png in Resources */,
+ D07CD4431C5D573600B7FB28 /* Default-736h@3x.png in Resources */,
+ D07CD43F1C5D573600B7FB28 /* Default-568h@2x~iphone.png in Resources */,
+ D07CD4451C5D573600B7FB28 /* Default-Landscape@2x~ipad.png in Resources */,
+ D07CD44A1C5D573600B7FB28 /* Default~iphone.png in Resources */,
+ D07CD4491C5D573600B7FB28 /* Default@2x~iphone.png in Resources */,
+ D07CD4441C5D573600B7FB28 /* Default-Landscape-736h.png in Resources */,
+ D07CD4421C5D573600B7FB28 /* Default-736h.png in Resources */,
+ D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */,
+ D0BCFE7A18AEC06A004A7AAE /* godot_opt.iphone in Resources */,
+ D07CD4481C5D573600B7FB28 /* Default-Portrait~ipad.png in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D0BCFE3018AEBDA2004A7AAE /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ D0BCFE4518AEBDA2004A7AAE /* en */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ D0BCFE6F18AEBDA3004A7AAE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ D0BCFE7018AEBDA3004A7AAE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ D0BCFE7218AEBDA3004A7AAE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD)";
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch";
+ INFOPLIST_FILE = "godot_ios/godot_ios-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.godotengine.game.ios;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = "armv7 armv7s";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ D0BCFE7318AEBDA3004A7AAE /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD)";
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Distribution: Ariel Manzur (BYC57PA2Q5)";
+ CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch";
+ INFOPLIST_FILE = "godot_ios/godot_ios-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 6.0;
+ PRODUCT_BUNDLE_IDENTIFIER = org.godotengine.game.ios;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALID_ARCHS = "armv7 armv7s";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "godot_ios" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D0BCFE6F18AEBDA3004A7AAE /* Debug */,
+ D0BCFE7018AEBDA3004A7AAE /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_ios" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D0BCFE7218AEBDA3004A7AAE /* Debug */,
+ D0BCFE7318AEBDA3004A7AAE /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = D0BCFE2C18AEBDA2004A7AAE /* Project object */;
+}
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..3c9ba38bbe
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:godot_ios.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png
new file mode 100644
index 0000000000..1341174454
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-568h@2x~iphone.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h.png
new file mode 100644
index 0000000000..c480d2e3c0
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h@2x.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h@2x.png
new file mode 100644
index 0000000000..3cc1dfa290
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-667h@2x.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h.png
new file mode 100644
index 0000000000..813d689162
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h@3x.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h@3x.png
new file mode 100644
index 0000000000..7707005e76
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-736h@3x.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape-736h.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape-736h.png
new file mode 100644
index 0000000000..b02873323e
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape-736h.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png
new file mode 100644
index 0000000000..d86c4a2510
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape@2x~ipad.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png
new file mode 100644
index 0000000000..e4f6cef02b
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Landscape~ipad.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png
new file mode 100644
index 0000000000..f306652a31
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait@2x~ipad.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png
new file mode 100644
index 0000000000..71a16db6df
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default-Portrait~ipad.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default@2x~iphone.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default@2x~iphone.png
new file mode 100644
index 0000000000..5305cb9bdb
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default@2x~iphone.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Default~iphone.png b/platform/iphone/xcode/godot_xcode/godot_ios/Default~iphone.png
new file mode 100644
index 0000000000..91c62d1e43
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Default~iphone.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..a458b67873
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,128 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "1x",
+ "filename": "Icon-29.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x",
+ "filename": "Icon-58.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x",
+ "filename": "icon-87.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x",
+ "filename": "Icon-80.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x",
+ "filename": "Icon-120.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "57x57",
+ "scale" : "1x",
+ "filename": "Icon-57.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "57x57",
+ "scale" : "2x",
+ "filename": "Icon-114.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x",
+ "filename": "Icon-120.png",
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x",
+ "filename": "Icon-180.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x",
+ "filename": "Icon-29.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x",
+ "filename": "Icon-58.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x",
+ "filename": "Icon-40.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x",
+ "filename": "Icon-80.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "50x50",
+ "scale" : "1x",
+ "filename": "Icon-50.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "50x50",
+ "scale" : "2x",
+ "filename": "Icon-100.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "72x72",
+ "scale" : "1x",
+ "filename": "Icon-72.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "72x72",
+ "scale" : "2x",
+ "filename": "Icon-144.png",
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "Icon-76.png",
+ "scale" : "1x",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x",
+ "filename": "Icon-152.png",
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x",
+ "filename": "icon-167.png",
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png
new file mode 100644
index 0000000000..f9dca1ab57
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png
new file mode 100644
index 0000000000..e7f9bd7388
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png
new file mode 100644
index 0000000000..4faa0f28e2
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png
new file mode 100644
index 0000000000..1c4cb51d56
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png
new file mode 100644
index 0000000000..e99b11c519
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png
new file mode 100644
index 0000000000..3edbcadfc5
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png
new file mode 100644
index 0000000000..0ae5893203
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png
new file mode 100644
index 0000000000..bb4ffa70ad
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png
new file mode 100644
index 0000000000..7a4b7107e7
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png
new file mode 100644
index 0000000000..b00bd79091
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png
new file mode 100644
index 0000000000..46335efdf6
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png
new file mode 100644
index 0000000000..2c9c2b61dc
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png
new file mode 100644
index 0000000000..d711958ef1
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png
new file mode 100644
index 0000000000..464e7e7289
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png
new file mode 100644
index 0000000000..1151bc6b4b
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png
new file mode 100644
index 0000000000..487c8326be
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png
new file mode 100644
index 0000000000..e54cee23a6
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png
Binary files differ
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes
new file mode 100644
index 0000000000..e328a62cb6
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes
@@ -0,0 +1,17 @@
+100
+114
+120
+144
+152
+167
+180
+29
+40
+50
+57
+58
+60
+72
+76
+80
+87
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings b/platform/iphone/xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings
new file mode 100644
index 0000000000..477b28ff8f
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
diff --git a/platform/iphone/xcode/godot_xcode/godot_ios/godot_ios-Info.plist b/platform/iphone/xcode/godot_xcode/godot_ios/godot_ios-Info.plist
new file mode 100644
index 0000000000..f97b0fca36
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/godot_ios-Info.plist
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>Insert Name Here</string>
+ <key>CFBundleExecutable</key>
+ <string>godot_opt.iphone</string>
+ <key>CFBundleIcons</key>
+ <dict/>
+ <key>CFBundleIcons~ipad</key>
+ <dict/>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UIRequiresFullScreen</key>
+ <true/>
+ <key>UIStatusBarHidden</key>
+ <true/>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/core/os/pc_joystick_map.h b/platform/iphone/xcode/godot_xcode/godot_ios/main.m
index df123c5c1b..3e4ea5e129 100644
--- a/core/os/pc_joystick_map.h
+++ b/platform/iphone/xcode/godot_xcode/godot_ios/main.m
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* pc_joystick_map.h */
+/* main.m */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -26,61 +26,14 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PC_JOYSTICK_MAP_H
-#define PC_JOYSTICK_MAP_H
-#include "input_event.h"
+#import <UIKit/UIKit.h>
-static const int _pc_joystick_button_remap[JOY_BUTTON_MAX]={
+#import "AppDelegate.h"
- JOY_SELECT,
- JOY_L3,
- JOY_R3,
- JOY_START,
-
- JOY_DPAD_UP,
- JOY_DPAD_RIGHT,
- JOY_DPAD_DOWN,
- JOY_DPAD_LEFT,
-
- JOY_L2,
- JOY_R2,
- JOY_L,
- JOY_R,
-
- JOY_SNES_X,
- JOY_SNES_A,
- JOY_SNES_B,
- JOY_SNES_Y,
-
- // JOY_HOME = 16
-};
-
-
-static int _pc_joystick_get_native_button(int p_pc_button) {
-
- if (p_pc_button<0 || p_pc_button>=JOY_BUTTON_MAX)
- return p_pc_button;
- return _pc_joystick_button_remap[p_pc_button];
+int main(int argc, char * argv[])
+{
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
}
-
-static const int _pc_joystick_axis_remap[JOY_AXIS_MAX]={
- JOY_ANALOG_0_X,
- JOY_ANALOG_0_Y,
- JOY_ANALOG_1_X,
- JOY_ANALOG_1_Y,
- JOY_ANALOG_2_X,
- JOY_ANALOG_2_Y,
- JOY_AXIS_6,
- JOY_AXIS_7
-};
-
-
-static int _pc_joystick_get_native_axis(int p_pc_axis) {
-
- if (p_pc_axis<0 || p_pc_axis>=JOY_BUTTON_MAX)
- return p_pc_axis;
- return _pc_joystick_axis_remap[p_pc_axis];
-}
-
-#endif // PC_JOYSTICK_MAP_H
diff --git a/platform/iphone/xcode/godot_xcode/godot_opt.iphone b/platform/iphone/xcode/godot_xcode/godot_opt.iphone
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/platform/iphone/xcode/godot_xcode/godot_opt.iphone
diff --git a/platform/nacl/nacl_keycodes.h b/platform/nacl/nacl_keycodes.h
index 45dba075db..a0642fc3b7 100644
--- a/platform/nacl/nacl_keycodes.h
+++ b/platform/nacl/nacl_keycodes.h
@@ -286,7 +286,7 @@ static uint32_t godot_key(uint32_t p_key, bool& is_char) {
case VKEY_MULTIPLY: return KEY_KP_MULTIPLY;
case VKEY_ADD: return KEY_KP_ADD;
// case VKEY_SEPARATOR: return KEY_SEPARATOR;
- case VKEY_SUBTRACT: return KEY_KP_SUBSTRACT;
+ case VKEY_SUBTRACT: return KEY_KP_SUBTRACT;
case VKEY_DECIMAL: return KEY_KP_PERIOD;
case VKEY_DIVIDE: return KEY_KP_DIVIDE;
case VKEY_F1: return KEY_F1;
diff --git a/platform/osx/audio_driver_osx.cpp b/platform/osx/audio_driver_osx.cpp
index a74303e6c2..d9d91b22fb 100644
--- a/platform/osx/audio_driver_osx.cpp
+++ b/platform/osx/audio_driver_osx.cpp
@@ -172,6 +172,9 @@ void AudioDriverOSX::unlock() {
void AudioDriverOSX::finish() {
+ if (active)
+ AudioOutputUnitStop(audio_unit);
+
memdelete_arr(samples_in);
};
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 2bb35fdc60..bb99e6ade7 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -650,7 +650,7 @@ static int translateKey(unsigned int key)
/* 4b */ KEY_KP_DIVIDE,
/* 4c */ KEY_KP_ENTER,
/* 4d */ KEY_UNKNOWN,
- /* 4e */ KEY_KP_SUBSTRACT,
+ /* 4e */ KEY_KP_SUBTRACT,
/* 4f */ KEY_UNKNOWN,
/* 50 */ KEY_UNKNOWN,
/* 51 */ KEY_EQUAL, //wtf equal?
@@ -809,6 +809,21 @@ static int translateKey(unsigned int key)
OS_OSX::singleton->push_input(ev);
}
+ if (fabs(deltaX)) {
+
+ InputEvent ev;
+ ev.type=InputEvent::MOUSE_BUTTON;
+ ev.mouse_button.button_index=deltaX >0 ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT;
+ ev.mouse_button.pressed=true;
+ ev.mouse_button.x=mouse_x;
+ ev.mouse_button.y=mouse_y;
+ ev.mouse_button.global_x=mouse_x;
+ ev.mouse_button.global_y=mouse_y;
+ ev.mouse_button.button_mask=button_mask;
+ OS_OSX::singleton->push_input(ev);
+ ev.mouse_button.pressed=false;
+ OS_OSX::singleton->push_input(ev);
+ }
}
@end
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 0d7ee64d80..1ad0f164d2 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -262,7 +262,7 @@ def configure(env):
env.Append(CCFLAGS=["/I"+DIRECTX_PATH+"/Include"])
env.Append(LIBPATH=[DIRECTX_PATH+"/Lib/x86"])
env['ENV'] = os.environ;
- env["x86_opt_vc"]=env["bits"]!="64"
+ env["x86_opt_vc"]=True
else:
# Workaround for MinGW. See:
@@ -305,7 +305,7 @@ def configure(env):
if (env["target"]=="release"):
- env.Append(CCFLAGS=['-ffast-math','-fomit-frame-pointer','-msse2'])
+ env.Append(CCFLAGS=['-msse2'])
if (env["bits"]=="64"):
env.Append(CCFLAGS=['-O3'])
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 899edde087..952f51fdd4 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -1,345 +1,6 @@
-/*************************************************************************/
-/* export.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
#include "export.h"
#include "platform/windows/logo.h"
-#include "os/os.h"
-#include "globals.h"
-#include "tools/editor/editor_node.h"
-#include "tools/pe_bliss/pe_bliss_godot.h"
-
-/**
- @author Masoud BaniHashemian <masoudbh3@gmail.com>
-*/
-
-
-void EditorExportPlatformWindows::store_16(DVector<uint8_t>& vector, uint16_t value) {
- const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&value);
- int size = vector.size();
- vector.resize( size + 2 );
- DVector<uint8_t>::Write w = vector.write();
- w[size]=bytes[0];
- w[size+1]=bytes[1];
-}
-void EditorExportPlatformWindows::store_32(DVector<uint8_t>& vector, uint32_t value) {
- const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&value);
- int size = vector.size();
- vector.resize( size + 4 );
- DVector<uint8_t>::Write w = vector.write();
- w[size]=bytes[0];
- w[size+1]=bytes[1];
- w[size+2]=bytes[2];
- w[size+3]=bytes[3];
-}
-
-bool EditorExportPlatformWindows::_set(const StringName& p_name, const Variant& p_value) {
-
- String n = p_name;
-
- if (n=="icon/icon_ico") {
-
- icon_ico=p_value;
- } else if (n=="icon/icon_png") {
-
- icon_png=p_value;
- } else if (n=="icon/icon_png16x16") {
-
- icon16=p_value;
- } else if (n=="icon/icon_png32x32") {
-
- icon32=p_value;
- } else if (n=="icon/icon_png48x48") {
-
- icon48=p_value;
- } else if (n=="icon/icon_png64x64") {
-
- icon64=p_value;
- } else if (n=="icon/icon_png128x128") {
-
- icon128=p_value;
- } else if (n=="icon/icon_png256x256") {
-
- icon256=p_value;
- } else if (n=="version_info/version_major") {
-
- version_major=p_value;
- } else if (n=="version_info/version_minor") {
-
- version_minor=p_value;
- } else if (n=="version_info/version_text") {
-
- version_text=p_value;
- } else if (n=="version_info/company_name") {
-
- company_name=p_value;
- } else if (n=="version_info/file_description") {
-
- file_description=p_value;
- } else if (n=="version_info/product_name") {
-
- product_name=p_value;
- } else if (n=="version_info/legal_copyright") {
-
- legal_copyright=p_value;
- } else if (n=="version_info/add_godot_version") {
-
- set_godot_version=p_value;
- } else
- return false;
-
- return true;
-
-}
-
-bool EditorExportPlatformWindows::_get(const StringName& p_name,Variant &r_ret) const {
-
- String n = p_name;
-
- if (n=="icon/icon_ico") {
-
- r_ret=icon_ico;
- } else if (n=="icon/icon_png") {
-
- r_ret=icon_png;
- } else if (n=="icon/icon_png16x16") {
-
- r_ret=icon16;
- } else if (n=="icon/icon_png32x32") {
-
- r_ret=icon32;
- } else if (n=="icon/icon_png48x48") {
-
- r_ret=icon48;
- } else if (n=="icon/icon_png64x64") {
-
- r_ret=icon64;
- } else if (n=="icon/icon_png128x128") {
-
- r_ret=icon128;
- } else if (n=="icon/icon_png256x256") {
-
- r_ret=icon256;
- } else if (n=="version_info/version_major") {
-
- r_ret=version_major;
- } else if (n=="version_info/version_minor") {
-
- r_ret=version_minor;
- } else if (n=="version_info/version_text") {
-
- r_ret=version_text;
- } else if (n=="version_info/company_name") {
-
- r_ret=company_name;
- } else if (n=="version_info/file_description") {
-
- r_ret=file_description;
- } else if (n=="version_info/product_name") {
-
- r_ret=product_name;
- } else if (n=="version_info/legal_copyright") {
-
- r_ret=legal_copyright;
- } else if (n=="version_info/add_godot_version") {
-
- r_ret=set_godot_version;
- } else
- return false;
-
- return true;
-
-}
-
-void EditorExportPlatformWindows::_get_property_list( List<PropertyInfo> *p_list) const {
-
- p_list->push_back( PropertyInfo( Variant::STRING, "icon/icon_ico",PROPERTY_HINT_FILE,"ico") );
- p_list->push_back( PropertyInfo( Variant::STRING, "icon/icon_png",PROPERTY_HINT_FILE,"png") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "icon/icon_png16x16") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "icon/icon_png32x32") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "icon/icon_png48x48") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "icon/icon_png64x64") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "icon/icon_png128x128") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "icon/icon_png256x256") );
- p_list->push_back( PropertyInfo( Variant::INT, "version_info/version_major", PROPERTY_HINT_RANGE,"0,65535,1"));
- p_list->push_back( PropertyInfo( Variant::INT, "version_info/version_minor", PROPERTY_HINT_RANGE,"0,65535,0"));
- p_list->push_back( PropertyInfo( Variant::STRING, "version_info/version_text") );
- p_list->push_back( PropertyInfo( Variant::STRING, "version_info/company_name") );
- p_list->push_back( PropertyInfo( Variant::STRING, "version_info/file_description") );
- p_list->push_back( PropertyInfo( Variant::STRING, "version_info/product_name") );
- p_list->push_back( PropertyInfo( Variant::STRING, "version_info/legal_copyright") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "version_info/add_godot_version") );
-
-}
-
-Error EditorExportPlatformWindows::export_project(const String& p_path, bool p_debug, int p_flags) {
-
- Error err = EditorExportPlatformPC::export_project(p_path, p_debug, p_flags);
- if(err != OK)
- {
- return err;
- }
- EditorProgress ep("editexe","Edit EXE File",102);
- ep.step("Create ico file..",0);
-
- DVector<uint8_t> icon_content;
- if (this->icon_ico!="" && this->icon_ico.ends_with(".ico")) {
- FileAccess *f = FileAccess::open(this->icon_ico,FileAccess::READ);
- if (f) {
- icon_content.resize(f->get_len());
- DVector<uint8_t>::Write write = icon_content.write();
- f->get_buffer(write.ptr(),icon_content.size());
- f->close();
- memdelete(f);
- }
- } else if (this->icon_png!="" && this->icon_png.ends_with(".png") && (icon16 || icon32 || icon48 || icon64 || icon128 || icon256)) {
- #ifdef PNG_ENABLED
- Vector<Image> pngs;
- Image png;
- Error err_png = png.load(this->icon_png);
- if (err_png==OK && !png.empty()) {
- if(icon256) {
- Image icon_256(png);
- if(!(png.get_height()==256 && png.get_width()==256)) icon_256.resize(256,256);
- pngs.push_back(icon_256);
- }
- if(icon128) {
- Image icon_128(png);
- if(!(png.get_height()==128 && png.get_width()==128)) icon_128.resize(128,128);
- pngs.push_back(icon_128);
- }
- if(icon64) {
- Image icon_64(png);
- if(!(png.get_height()==64 && png.get_width()==64)) icon_64.resize(64,64);
- pngs.push_back(icon_64);
- }
- if(icon48) {
- Image icon_48(png);
- if(!(png.get_height()==48 && png.get_width()==48)) icon_48.resize(48,48);
- pngs.push_back(icon_48);
- }
- if(icon32) {
- Image icon_32(png);
- if(!(png.get_height()==32 && png.get_width()==32)) icon_32.resize(32,32);
- pngs.push_back(icon_32);
- }
- if(icon16) {
- Image icon_16(png);
- if(!(png.get_height()==16 && png.get_width()==16)) icon_16.resize(16,16);
- pngs.push_back(icon_16);
- }
- // create icon according to https://www.daubnet.com/en/file-format-ico
- store_16(icon_content,0); //Reserved
- store_16(icon_content,1); //Type
- store_16(icon_content,pngs.size()); //Count
- int offset = 6+pngs.size()*16;
- //List of bitmaps
- for(int i=0;i<pngs.size();i++) {
- int w = pngs[i].get_width();
- int h = pngs[i].get_height();
- icon_content.push_back(w<256?w:0); //width
- icon_content.push_back(h<256?h:0); //height
- icon_content.push_back(0); //ColorCount = 0
- icon_content.push_back(0); //Reserved
- store_16(icon_content,1); //Planes
- store_16(icon_content,32); //BitCount (bit per pixel)
- int size = 40 + (w * h * 4) + (w * h / 8);
- store_32(icon_content,size); //Size of (InfoHeader + ANDbitmap + XORbitmap)
- store_32(icon_content,offset); //FileOffset
- offset += size;
- }
- //Write bmp files.
- for(int i=0;i<pngs.size();i++) {
- int w = pngs[i].get_width();
- int h = pngs[i].get_height();
- store_32(icon_content,40); //Size of InfoHeader structure = 40
- store_32(icon_content,w); //Width
- store_32(icon_content,h*2); //Height
- store_16(icon_content,1); //Planes
- store_16(icon_content,32); //BitCount
- store_32(icon_content,0); //Compression
- store_32(icon_content,w*h*4); //ImageSize = Size of Image in Bytes
- store_32(icon_content,0); //unused = 0
- store_32(icon_content,0); //unused = 0
- store_32(icon_content,0); //unused = 0
- store_32(icon_content,0); //unused = 0
- //XORBitmap
- for(int y=h-1;y>=0;y--) {
- for(int x=0;x<w;x++) {
- store_32(icon_content,pngs[i].get_pixel(x,y).to_32());
- }
- }
- //ANDBitmap
- for(int m=0;m<(w * h / 8);m+=4) store_32(icon_content,0x00000000); // Add empty ANDBitmap , TODO create full ANDBitmap Structure if need.
- }
- }
- #endif
- }
-
- ep.step("Add rsrc..",50);
-
- String basename = Globals::get_singleton()->get("application/name");
- product_name=product_name.replace("$genname",basename);
- String godot_version;
- if(set_godot_version) godot_version = String( VERSION_MKSTRING );
- String ret = pe_bliss_add_resrc(p_path.utf8(), version_major, version_minor,
- company_name, file_description, legal_copyright, version_text,
- product_name, godot_version, icon_content);
- if (ret.empty()) {
- return OK;
- } else {
- EditorNode::add_io_error(ret);
- return ERR_FILE_CANT_WRITE;
- }
-}
-
-EditorExportPlatformWindows::EditorExportPlatformWindows() {
-
- icon16=true;
- icon32=true;
- icon48=true;
- icon64=true;
- icon128=true;
- icon256=true;
- product_name="$genname";
- company_name="Godot Engine";
- file_description="Created With Godot Engine";
- version_text="1.0";
- OS::Date date = OS::get_singleton()->get_date();
- legal_copyright="Copyright (c) 2007-";
- legal_copyright+=String::num(date.year);
- legal_copyright+=" Juan Linietsky, Ariel Manzur";
- version_major=1;
- version_minor=0;
- set_godot_version=true;
-}
-
-
+#include "tools/editor/editor_import_export.h"
void register_windows_exporter() {
@@ -348,7 +9,7 @@ void register_windows_exporter() {
logo->create_from_image(img);
{
- Ref<EditorExportPlatformWindows> exporter = Ref<EditorExportPlatformWindows>( memnew(EditorExportPlatformWindows) );
+ Ref<EditorExportPlatformPC> exporter = Ref<EditorExportPlatformPC>( memnew(EditorExportPlatformPC) );
exporter->set_binary_extension("exe");
exporter->set_release_binary32("windows_32_release.exe");
exporter->set_debug_binary32("windows_32_debug.exe");
diff --git a/platform/windows/export/export.h b/platform/windows/export/export.h
index 2424efc861..68ce500a20 100644
--- a/platform/windows/export/export.h
+++ b/platform/windows/export/export.h
@@ -1,37 +1,4 @@
-#include "tools/editor/editor_import_export.h"
-class EditorExportPlatformWindows : public EditorExportPlatformPC {
- OBJ_TYPE( EditorExportPlatformWindows,EditorExportPlatformPC );
-
-private:
- String icon_ico;
- String icon_png;
- bool icon16;
- bool icon32;
- bool icon48;
- bool icon64;
- bool icon128;
- bool icon256;
- String company_name;
- String file_description;
- String product_name;
- String legal_copyright;
- String version_text;
- int version_major;
- int version_minor;
- bool set_godot_version;
- void store_16(DVector<uint8_t>& vector, uint16_t value); ///< store 16 bits uint
- void store_32(DVector<uint8_t>& vector, uint32_t value); ///< store 32 bits uint
-
-protected:
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
-public:
- Error export_project(const String& p_path, bool p_debug,int p_flags=0);
- EditorExportPlatformWindows();
-};
void register_windows_exporter();
diff --git a/platform/windows/joystick.cpp b/platform/windows/joystick.cpp
index f4fb09820f..f8526b5ec1 100644
--- a/platform/windows/joystick.cpp
+++ b/platform/windows/joystick.cpp
@@ -472,7 +472,7 @@ InputDefault::JoyAxis joystick_windows::axis_correct(int p_val, bool p_xinput, b
InputDefault::JoyAxis jx;
if (Math::abs(p_val) < MIN_JOY_AXIS) {
- jx.min = -1;
+ jx.min = p_trigger ? 0 : -1;
jx.value = 0.0f;
return jx;
}
diff --git a/platform/windows/key_mapping_win.cpp b/platform/windows/key_mapping_win.cpp
index 07d5f32253..23fa29d68f 100644
--- a/platform/windows/key_mapping_win.cpp
+++ b/platform/windows/key_mapping_win.cpp
@@ -145,7 +145,7 @@ static _WinTranslatePair _vk_to_keycode[]={
{ KEY_KP_MULTIPLY,VK_MULTIPLY},// (0x6A)
{ KEY_KP_ADD,VK_ADD},// (0x6B)
//VK_SEPARATOR (0x6C)
-{ KEY_KP_SUBSTRACT,VK_SUBTRACT},// (0x6D)
+{ KEY_KP_SUBTRACT,VK_SUBTRACT},// (0x6D)
{ KEY_KP_PERIOD,VK_DECIMAL},// (0x6E)
{ KEY_KP_DIVIDE,VK_DIVIDE},// (0x6F)
{ KEY_F1,VK_F1},// (0x70)
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 886c43d116..95a6a6ac58 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -47,7 +47,6 @@
#include "tcp_server_winsock.h"
#include "packet_peer_udp_winsock.h"
#include "stream_peer_winsock.h"
-#include "os/pc_joystick_map.h"
#include "lang_table.h"
#include "os/memory_pool_dynamic_prealloc.h"
#include "globals.h"
@@ -67,6 +66,10 @@ extern "C" {
#endif
}
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020e
+#endif
+
//#define STDOUT_FILE
extern HINSTANCE godot_hinstance;
@@ -433,6 +436,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MOUSEWHEEL:
+ case WM_MOUSEHWHEEL:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
/*case WM_XBUTTONDOWN:
@@ -503,12 +507,24 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (motion>0)
- mb.button_index=4;
+ mb.button_index= BUTTON_WHEEL_UP;
else
- mb.button_index=5;
+ mb.button_index= BUTTON_WHEEL_DOWN;
} break;
+ case WM_MOUSEHWHEEL: {
+
+ mb.pressed = true;
+ int motion = (short)HIWORD(wParam);
+ if (!motion)
+ return 0;
+
+ if (motion<0)
+ mb.button_index = BUTTON_WHEEL_LEFT;
+ else
+ mb.button_index = BUTTON_WHEEL_RIGHT;
+ } break;
/*
case WM_XBUTTONDOWN: {
mb.pressed=true;
@@ -2059,7 +2075,7 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const {
id=CSIDL_MYPICTURES;
} break;
case SYSTEM_DIR_DOCUMENTS: {
- id=0x000C;
+ id=CSIDL_PERSONAL;
} break;
case SYSTEM_DIR_DOWNLOADS: {
id=0x000C ;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index e433d5cc11..ab4acf312c 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -29,7 +29,7 @@
#ifndef OS_WINDOWS_H
#define OS_WINDOWS_H
-#define WINVER 0x0500
+#define WINVER 0x0600
#include "os/input.h"
#include "os/os.h"
diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp
index f507c1aae7..b6ce7f950d 100644
--- a/platform/winrt/os_winrt.cpp
+++ b/platform/winrt/os_winrt.cpp
@@ -43,7 +43,6 @@
#include "servers/audio/audio_server_sw.h"
#include "servers/visual/visual_server_wrap_mt.h"
-#include "os/pc_joystick_map.h"
#include "os/memory_pool_dynamic_prealloc.h"
#include "globals.h"
#include "io/marshalls.h"
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index e035c72993..6b147db130 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -52,10 +52,11 @@ def get_opts():
return [
('use_llvm','Use llvm compiler','no'),
+ ('use_static_cpp','link stdc++ statically','no'),
('use_sanitizer','Use llvm compiler sanitize address','no'),
('use_leak_sanitizer','Use llvm compiler sanitize memory leaks','no'),
('pulseaudio','Detect & Use pulseaudio','yes'),
- ('gamepad','Gamepad support, requires libudev and libevdev','yes'),
+ ('udev','Use udev for gamepad connection callbacks','no'),
('new_wm_api', 'Use experimental window management API','no'),
('debug_release', 'Add debug symbols to release version','no'),
]
@@ -155,24 +156,18 @@ def configure(env):
else:
print("ALSA libraries not found, disabling driver")
- if (env["gamepad"]=="yes" and platform.system() == "Linux"):
+ if (platform.system() == "Linux"):
+ env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"])
+ if (env["udev"]=="yes"):
# pkg-config returns 0 when the lib exists...
found_udev = not os.system("pkg-config --exists libudev")
- found_evdev = not os.system("pkg-config --exists libevdev")
-
- if (found_udev and found_evdev):
- print("Enabling gamepad support with udev/evdev")
- env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"])
+
+ if (found_udev):
+ print("Enabling udev support")
+ env.Append(CPPFLAGS=["-DUDEV_ENABLED"])
env.ParseConfig('pkg-config libudev --cflags --libs')
- env.ParseConfig('pkg-config libevdev --cflags --libs')
else:
- if (not found_udev):
- print("libudev development libraries not found")
- if (not found_evdev):
- print("libevdev development libraries not found")
- print("Some libraries are missing for the required gamepad support, aborting!")
- print("Install the mentioned libraries or build with 'gamepad=no' to disable gamepad support.")
- sys.exit(255)
+ print("libudev development libraries not found, disabling udev support")
if (env["pulseaudio"]=="yes"):
if not os.system("pkg-config --exists libpulse-simple"):
@@ -207,5 +202,8 @@ def configure(env):
env.Append(CPPFLAGS=['-DNEW_WM_API'])
env.ParseConfig('pkg-config xinerama --cflags --libs')
+ if (env["use_static_cpp"]=="yes"):
+ env.Append(LINKFLAGS=['-static-libstdc++'])
+
env["x86_opt_gcc"]=True
diff --git a/platform/x11/joystick_linux.cpp b/platform/x11/joystick_linux.cpp
index 6eb3671bc0..9a52c4ff36 100644
--- a/platform/x11/joystick_linux.cpp
+++ b/platform/x11/joystick_linux.cpp
@@ -31,22 +31,38 @@
#ifdef JOYDEV_ENABLED
#include "joystick_linux.h"
-#include "print_string.h"
-#include <libevdev/libevdev.h>
-#include <libudev.h>
+#include <linux/input.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
-#include <cstring>
+
+#ifdef UDEV_ENABLED
+#include <libudev.h>
+#endif
+
+#define LONG_BITS (sizeof(long) * 8)
+#define test_bit(nr, addr) (((1UL << ((nr) % LONG_BITS)) & ((addr)[(nr) / LONG_BITS])) != 0)
+#define NBITS(x) ((((x)-1)/LONG_BITS)+1)
static const char* ignore_str = "/dev/input/js";
joystick_linux::Joystick::Joystick() {
fd = -1;
dpad = 0;
- dev = NULL;
devpath = "";
+ for (int i = 0; i < MAX_ABS; i++) {
+ abs_info[i] = NULL;
+ }
+}
+
+joystick_linux::Joystick::~Joystick() {
+
+ for (int i = 0; i < MAX_ABS; i++) {
+ if (abs_info[i]) {
+ memdelete(abs_info[i]);
+ }
+ }
}
void joystick_linux::Joystick::reset() {
@@ -86,14 +102,18 @@ void joystick_linux::joy_thread_func(void *p_user) {
}
void joystick_linux::run_joystick_thread() {
-
+#ifdef UDEV_ENABLED
udev *_udev = udev_new();
ERR_FAIL_COND(!_udev);
enumerate_joysticks(_udev);
monitor_joysticks(_udev);
udev_unref(_udev);
+#else
+ monitor_joysticks();
+#endif
}
+#ifdef UDEV_ENABLED
void joystick_linux::enumerate_joysticks(udev *p_udev) {
udev_enumerate *enumerate;
@@ -112,10 +132,14 @@ void joystick_linux::enumerate_joysticks(udev *p_udev) {
dev = udev_device_new_from_syspath(p_udev, path);
const char* devnode = udev_device_get_devnode(dev);
- if (devnode != NULL && strstr(devnode, ignore_str) == NULL) {
- joy_mutex->lock();
- open_joystick(devnode);
- joy_mutex->unlock();
+ if (devnode) {
+
+ String devnode_str = devnode;
+ if (devnode_str.find(ignore_str) == -1) {
+ joy_mutex->lock();
+ open_joystick(devnode);
+ joy_mutex->unlock();
+ }
}
udev_device_unref(dev);
}
@@ -146,22 +170,24 @@ void joystick_linux::monitor_joysticks(udev *p_udev) {
/* Check if our file descriptor has received data. */
if (ret > 0 && FD_ISSET(fd, &fds)) {
/* Make the call to receive the device.
- select() ensured that this will not block. */
+ select() ensured that this will not block. */
dev = udev_monitor_receive_device(mon);
if (dev && udev_device_get_devnode(dev) != 0) {
joy_mutex->lock();
- const char* action = udev_device_get_action(dev);
+ String action = udev_device_get_action(dev);
const char* devnode = udev_device_get_devnode(dev);
+ if (devnode) {
- if (strstr(devnode, ignore_str) == NULL) {
+ String devnode_str = devnode;
+ if (devnode_str.find(ignore_str) == -1) {
- if (strcmp(action, "add") == 0)
- open_joystick(devnode);
-
- else if (strcmp(action, "remove") == 0)
- close_joystick(get_joy_from_path(devnode));
+ if (action == "add")
+ open_joystick(devnode);
+ else if (String(action) == "remove")
+ close_joystick(get_joy_from_path(devnode));
+ }
}
udev_device_unref(dev);
@@ -173,6 +199,23 @@ void joystick_linux::monitor_joysticks(udev *p_udev) {
//printf("exit udev\n");
udev_monitor_unref(mon);
}
+#endif
+
+void joystick_linux::monitor_joysticks() {
+
+ while (!exit_udev) {
+ joy_mutex->lock();
+ for (int i = 0; i < 32; i++) {
+ char fname[64];
+ sprintf(fname, "/dev/input/event%d", i);
+ if (attached_devices.find(fname) == -1) {
+ open_joystick(fname);
+ }
+ }
+ joy_mutex->unlock();
+ usleep(1000000); // 1s
+ }
+}
int joystick_linux::get_free_joy_slot() const {
@@ -208,9 +251,9 @@ void joystick_linux::close_joystick(int p_id) {
if (joy.fd != -1) {
- libevdev_free(joy.dev);
close(joy.fd);
joy.fd = -1;
+ attached_devices.remove(attached_devices.find(joy.devpath));
input->joy_connection_changed(p_id, false, "");
};
};
@@ -230,21 +273,27 @@ static String _hex_str(uint8_t p_byte) {
void joystick_linux::setup_joystick_properties(int p_id) {
Joystick* joy = &joysticks[p_id];
- libevdev* dev = joy->dev;
+
+ unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
+ unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
int num_buttons = 0;
int num_axes = 0;
+ if ((ioctl(joy->fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
+ (ioctl(joy->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
+ return;
+ }
for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
- if (libevdev_has_event_code(dev, EV_KEY, i)) {
+ if (test_bit(i, keybit)) {
joy->key_map[i] = num_buttons++;
}
}
for (int i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
- if (libevdev_has_event_code(dev, EV_KEY, i)) {
+ if (test_bit(i, keybit)) {
joy->key_map[i] = num_buttons++;
}
@@ -255,68 +304,88 @@ void joystick_linux::setup_joystick_properties(int p_id) {
i = ABS_HAT3Y;
continue;
}
- if (libevdev_has_event_code(dev, EV_ABS, i)) {
+ if (test_bit(i, absbit)) {
joy->abs_map[i] = num_axes++;
+ joy->abs_info[i] = memnew(input_absinfo);
+ if (ioctl(joy->fd, EVIOCGABS(i), joy->abs_info[i]) < 0) {
+ memdelete(joy->abs_info[i]);
+ joy->abs_info[i] = NULL;
+ }
}
}
}
+
void joystick_linux::open_joystick(const char *p_path) {
int joy_num = get_free_joy_slot();
int fd = open(p_path, O_RDONLY | O_NONBLOCK);
if (fd != -1 && joy_num != -1) {
- int rc = libevdev_new_from_fd(fd, &joysticks[joy_num].dev);
- if (rc < 0) {
+ unsigned long evbit[NBITS(EV_MAX)] = { 0 };
+ unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
+ unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
+
+ // add to attached devices so we don't try to open it again
+ attached_devices.push_back(String(p_path));
- fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
+ if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
+ (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
+ (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
+ close(fd);
return;
}
- libevdev *dev = joysticks[joy_num].dev;
-
//check if the device supports basic gamepad events, prevents certain keyboards from
//being detected as joysticks
- if (libevdev_has_event_type(dev, EV_ABS) && libevdev_has_event_type(dev, EV_KEY) &&
- (libevdev_has_event_code(dev, EV_KEY, BTN_A) || libevdev_has_event_code(dev, EV_KEY, BTN_THUMBL) || libevdev_has_event_code(dev, EV_KEY, BTN_TOP))) {
-
- char uid[128];
- String name = libevdev_get_name(dev);
- uint16_t bus = __bswap_16(libevdev_get_id_bustype(dev));
- uint16_t vendor = __bswap_16(libevdev_get_id_vendor(dev));
- uint16_t product = __bswap_16(libevdev_get_id_product(dev));
- uint16_t version = __bswap_16(libevdev_get_id_version(dev));
-
- joysticks[joy_num].reset();
-
- Joystick &joy = joysticks[joy_num];
- joy.fd = fd;
- joy.devpath = String(p_path);
- setup_joystick_properties(joy_num);
- sprintf(uid, "%04x%04x", bus, 0);
- if (vendor && product && version) {
-
- sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor,0,product,0,version,0);
- input->joy_connection_changed(joy_num, true, name, uid);
- }
- else {
- String uidname = uid;
- int uidlen = MIN(name.length(), 11);
- for (int i=0; i<uidlen; i++) {
+ if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
+ (test_bit(ABS_X, absbit) || test_bit(ABS_Y, absbit) || test_bit(ABS_HAT0X, absbit) ||
+ test_bit(ABS_GAS, absbit) || test_bit(ABS_RUDDER, absbit)) &&
+ (test_bit(BTN_A, keybit) || test_bit(BTN_THUMBL, keybit) ||
+ test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_1, keybit)))) {
+ close(fd);
+ return;
+ }
- uidname = uidname + _hex_str(name[i]);
- }
- uidname += "00";
- input->joy_connection_changed(joy_num, true, name, uidname);
+ char uid[128];
+ char namebuf[128];
+ String name = "";
+ input_id inpid;
+ if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) >= 0) {
+ name = namebuf;
+ }
- }
+ if (ioctl(fd, EVIOCGID, &inpid) < 0) {
+ close(fd);
+ return;
+ }
+
+ joysticks[joy_num].reset();
+
+ Joystick &joy = joysticks[joy_num];
+ joy.fd = fd;
+ joy.devpath = String(p_path);
+ setup_joystick_properties(joy_num);
+ sprintf(uid, "%04x%04x", __bswap_16(inpid.bustype), 0);
+ if (inpid.vendor && inpid.product && inpid.version) {
+
+ uint16_t vendor = __bswap_16(inpid.vendor);
+ uint16_t product = __bswap_16(inpid.product);
+ uint16_t version = __bswap_16(inpid.version);
+
+ sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor,0,product,0,version,0);
+ input->joy_connection_changed(joy_num, true, name, uid);
}
else {
- //device is not a gamepad, clean up
- libevdev_free(dev);
- close(fd);
+ String uidname = uid;
+ int uidlen = MIN(name.length(), 11);
+ for (int i=0; i<uidlen; i++) {
+
+ uidname = uidname + _hex_str(name[i]);
+ }
+ uidname += "00";
+ input->joy_connection_changed(joy_num, true, name, uidname);
}
}
}
@@ -350,58 +419,54 @@ uint32_t joystick_linux::process_joysticks(uint32_t p_event_id) {
if (joysticks[i].fd == -1) continue;
- input_event ev;
+ input_event events[32];
Joystick* joy = &joysticks[i];
- libevdev* dev = joy->dev;
- int rc = 1;
-
- rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
-
- if (rc < 0 && rc != -EAGAIN) {
- continue;
- }
-
- while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS) {
-
- switch (ev.type) {
- case EV_KEY:
- p_event_id = input->joy_button(p_event_id, i, joy->key_map[ev.code], ev.value);
- break;
- case EV_ABS:
+ int len;
- switch (ev.code) {
- case ABS_HAT0X:
- if (ev.value != 0) {
- if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_LEFT;
- else joy->dpad |= InputDefault::HAT_MASK_RIGHT;
+ while ((len = read(joy->fd, events, (sizeof events))) > 0) {
+ len /= sizeof(events[0]);
+ for (int j = 0; j < len; j++) {
- }
- else joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT);
-
- p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
- break;
-
- case ABS_HAT0Y:
- if (ev.value != 0) {
- if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_UP;
- else joy->dpad |= InputDefault::HAT_MASK_DOWN;
- }
- else joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN);
-
- p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
+ input_event &ev = events[j];
+ switch (ev.type) {
+ case EV_KEY:
+ p_event_id = input->joy_button(p_event_id, i, joy->key_map[ev.code], ev.value);
break;
- default:
- if (joy->abs_map[ev.code] != -1) {
- InputDefault::JoyAxis value = axis_correct(libevdev_get_abs_info(dev, ev.code), ev.value);
- joy->curr_axis[joy->abs_map[ev.code]] = value;
+ case EV_ABS:
+
+ switch (ev.code) {
+ case ABS_HAT0X:
+ if (ev.value != 0) {
+ if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_LEFT;
+ else joy->dpad |= InputDefault::HAT_MASK_RIGHT;
+ }
+ else joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT);
+
+ p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
+ break;
+
+ case ABS_HAT0Y:
+ if (ev.value != 0) {
+ if (ev.value < 0) joy->dpad |= InputDefault::HAT_MASK_UP;
+ else joy->dpad |= InputDefault::HAT_MASK_DOWN;
+ }
+ else joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN);
+
+ p_event_id = input->joy_hat(p_event_id, i, joy->dpad);
+ break;
+
+ default:
+ if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) {
+ InputDefault::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value);
+ joy->curr_axis[joy->abs_map[ev.code]] = value;
+ }
+ break;
}
break;
}
- break;
}
- rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
}
for (int j = 0; j < MAX_ABS; j++) {
int index = joy->abs_map[j];
@@ -409,6 +474,9 @@ uint32_t joystick_linux::process_joysticks(uint32_t p_event_id) {
p_event_id = input->joy_axis(p_event_id, i, index, joy->curr_axis[index]);
}
}
+ if (len == 0 || (len < 0 && errno != EAGAIN)) {
+ close_joystick(i);
+ };
}
joy_mutex->unlock();
return p_event_id;
diff --git a/platform/x11/joystick_linux.h b/platform/x11/joystick_linux.h
index ee9bd0352a..e433f5e8e3 100644
--- a/platform/x11/joystick_linux.h
+++ b/platform/x11/joystick_linux.h
@@ -61,9 +61,10 @@ private:
int fd;
String devpath;
- struct libevdev *dev;
+ input_absinfo *abs_info[MAX_ABS];
Joystick();
+ ~Joystick();
void reset();
};
@@ -72,6 +73,7 @@ private:
Thread *joy_thread;
InputDefault *input;
Joystick joysticks[JOYSTICKS_MAX];
+ Vector<String> attached_devices;
static void joy_thread_func(void *p_user);
@@ -80,8 +82,11 @@ private:
void setup_joystick_properties(int p_id);
void close_joystick(int p_id = -1);
+#ifdef UDEV_ENABLED
void enumerate_joysticks(struct udev *_udev);
void monitor_joysticks(struct udev *_udev);
+#endif
+ void monitor_joysticks();
void run_joystick_thread();
void open_joystick(const char* path);
diff --git a/platform/x11/key_mapping_x11.cpp b/platform/x11/key_mapping_x11.cpp
index 48f415a730..46f1483767 100644
--- a/platform/x11/key_mapping_x11.cpp
+++ b/platform/x11/key_mapping_x11.cpp
@@ -97,7 +97,7 @@ static _XTranslatePair _xkeysym_to_keycode[]={
{ XK_KP_Enter, KEY_KP_ENTER },
{ XK_KP_Multiply, KEY_KP_MULTIPLY},
{ XK_KP_Divide, KEY_KP_DIVIDE},
- { XK_KP_Subtract, KEY_KP_SUBSTRACT},
+ { XK_KP_Subtract, KEY_KP_SUBTRACT},
{ XK_KP_Add, KEY_KP_ADD},
{ XK_KP_0, KEY_KP_0},
{ XK_KP_1, KEY_KP_1},
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index f42e93b93f..e5591810e7 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -65,7 +65,6 @@
#include <X11/Xatom.h>
-//#include "os/pc_joystick_map.h"
#undef CursorShape
@@ -575,6 +574,10 @@ Point2 OS_X11::get_mouse_pos() const {
void OS_X11::set_window_title(const String& p_title) {
XStoreName(x11_display,x11_window,p_title.utf8().get_data());
+
+ Atom _net_wm_name = XInternAtom(x11_display, "_NET_WM_NAME", false);
+ Atom utf8_string = XInternAtom(x11_display, "UTF8_STRING", false);
+ XChangeProperty( x11_display, x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char*) p_title.utf8().get_data(), p_title.utf8().length());
}
void OS_X11::set_video_mode(const VideoMode& p_video_mode,int p_screen) {
@@ -1782,6 +1785,22 @@ String OS_X11::get_joy_guid(int p_device) const {
return input->get_joy_guid_remapped(p_device);
}
+void OS_X11::set_context(int p_context) {
+
+ XClassHint* classHint = NULL;
+ classHint = XAllocClassHint();
+ if (classHint) {
+
+ if (p_context == CONTEXT_EDITOR)
+ classHint->res_name = (char *)"Godot_Editor";
+ if (p_context == CONTEXT_PROJECTMAN)
+ classHint->res_name = (char *)"Godot_ProjectList";
+ classHint->res_class = (char *)"Godot";
+ XSetClassHint(x11_display, x11_window, classHint);
+ XFree(classHint);
+ }
+}
+
OS_X11::OS_X11() {
#ifdef RTAUDIO_ENABLED
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 91dbeac284..0891e4b8eb 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -226,6 +226,8 @@ public:
virtual bool is_joy_known(int p_device);
virtual String get_joy_guid(int p_device) const;
+ virtual void set_context(int p_context);
+
void run();
OS_X11();
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index 4c00d8cec9..376aeb2d85 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -429,8 +429,8 @@ void NavigationPolygonInstance::_navpoly_changed() {
void NavigationPolygonInstance::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_navigation_polygon","navpoly"),&NavigationPolygonInstance::set_navigation_polygon);
- ObjectTypeDB::bind_method(_MD("get_navigation_polygon"),&NavigationPolygonInstance::get_navigation_polygon);
+ ObjectTypeDB::bind_method(_MD("set_navigation_polygon","navpoly:NavigationPolygon"),&NavigationPolygonInstance::set_navigation_polygon);
+ ObjectTypeDB::bind_method(_MD("get_navigation_polygon:NavigationPolygon"),&NavigationPolygonInstance::get_navigation_polygon);
ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&NavigationPolygonInstance::set_enabled);
ObjectTypeDB::bind_method(_MD("is_enabled"),&NavigationPolygonInstance::is_enabled);
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 179d1f451a..1cd6399962 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -450,6 +450,7 @@ void TileMap::_update_dirty_quadrants() {
_fix_cell_transform(xform,c,shape_ofs+center_ofs,s);
if (debug_canvas_item) {
+ vs->canvas_item_add_set_transform(debug_canvas_item,xform);
shape->draw(debug_canvas_item,debug_collision_color);
}
@@ -459,6 +460,10 @@ void TileMap::_update_dirty_quadrants() {
}
}
+ if (debug_canvas_item) {
+ vs->canvas_item_add_set_transform(debug_canvas_item,Matrix32());
+ }
+
if (navigation) {
Ref<NavigationPolygon> navpoly = tile_set->tile_get_navigation_polygon(c.id);
if (navpoly.is_valid()) {
@@ -694,6 +699,10 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bo
}
+int TileMap::get_cellv(const Vector2& p_pos) const {
+ return get_cell(p_pos.x,p_pos.y);
+}
+
int TileMap::get_cell(int p_x,int p_y) const {
PosKey pk(p_x,p_y);
@@ -1198,8 +1207,10 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("set_cellv","pos","tile","flip_x","flip_y","transpose"),&TileMap::set_cellv,DEFVAL(false),DEFVAL(false),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
+ ObjectTypeDB::bind_method(_MD("get_cellv","pos"),&TileMap::get_cellv);
ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);
+ ObjectTypeDB::bind_method(_MD("is_cell_transposed","x","y"),&TileMap::is_cell_transposed);
ObjectTypeDB::bind_method(_MD("clear"),&TileMap::clear);
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 14cb52b736..cec5ac0a1b 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -211,6 +211,7 @@ public:
bool is_cell_transposed(int p_x,int p_y) const;
void set_cellv(const Vector2& p_pos,int p_tile,bool p_flip_x=false,bool p_flip_y=false,bool p_transpose=false);
+ int get_cellv(const Vector2& p_pos) const;
Rect2 get_item_rect() const;
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 3e78fef147..01163e40e8 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -213,8 +213,7 @@ void Camera::_notification(int p_what) {
case NOTIFICATION_ENTER_WORLD: {
- bool first_camera = get_viewport()->cameras.size()==0;
- get_viewport()->cameras.insert(this);
+ bool first_camera = get_viewport()->_camera_add(this);
if (!get_tree()->is_node_being_edited(this) && (current || first_camera))
make_current();
@@ -236,7 +235,7 @@ void Camera::_notification(int p_what) {
}
}
- get_viewport()->cameras.erase(this);
+ get_viewport()->_camera_remove(this);
} break;
@@ -304,7 +303,7 @@ void Camera::make_current() {
if (!is_inside_tree())
return;
- get_viewport()->_set_camera(this);
+ get_viewport()->_camera_set(this);
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this);
}
@@ -319,20 +318,8 @@ void Camera::clear_current() {
return;
if (get_viewport()->get_camera()==this) {
- get_viewport()->_set_camera(NULL);
- //a group is used beause this needs to be in order to be deterministic
-
- for (Set<Camera*>::Element *E=get_viewport()->cameras.front();E;E=E->next()) {
-
- if (this==E->get())
- continue;
- if (!E->get()->is_inside_tree())
- continue;
- if (get_viewport()->get_camera()!=NULL)
- return;
-
- E->get()->make_current();
- }
+ get_viewport()->_camera_set(NULL);
+ get_viewport()->_camera_make_next_current(this);
}
}
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index dfd5c38266..47662bcccb 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -95,7 +95,7 @@ DVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const {
void Particles::set_amount(int p_amount) {
- ERR_FAIL_INDEX(p_amount,4096);
+ ERR_FAIL_INDEX(p_amount,1024);
amount=p_amount;
VisualServer::get_singleton()->particles_set_amount(particles,p_amount);
}
@@ -441,7 +441,7 @@ void Particles::_bind_methods() {
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material" ), _SCS("set_material"), _SCS("get_material") );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,4096,1" ), _SCS("set_amount"), _SCS("get_amount") );
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1024,1" ), _SCS("set_amount"), _SCS("get_amount") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "emitting" ), _SCS("set_emitting"), _SCS("is_emitting") );
ADD_PROPERTY( PropertyInfo( Variant::_AABB, "visibility" ), _SCS("set_visibility_aabb"), _SCS("get_visibility_aabb") );
ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_extents" ), _SCS("set_emission_half_extents"), _SCS("get_emission_half_extents") );
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index f6d058c2fd..0bc54b3d43 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -147,14 +147,21 @@ void AnimationPlayer::_get_property_list( List<PropertyInfo> *p_list) const {
List<String> names;
+ List<PropertyInfo> anim_names;
+
for( Map<StringName, AnimationData>::Element *E=animation_set.front();E;E=E->next()) {
- p_list->push_back( PropertyInfo( Variant::OBJECT, "anims/"+String(E->key()), PROPERTY_HINT_RESOURCE_TYPE, "Animation",PROPERTY_USAGE_NOEDITOR) );
+ anim_names.push_back( PropertyInfo( Variant::OBJECT, "anims/"+String(E->key()), PROPERTY_HINT_RESOURCE_TYPE, "Animation",PROPERTY_USAGE_NOEDITOR) );
if (E->get().next!=StringName())
- p_list->push_back( PropertyInfo( Variant::STRING, "next/"+String(E->key()), PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR) );
+ anim_names.push_back( PropertyInfo( Variant::STRING, "next/"+String(E->key()), PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR) );
names.push_back(E->key());
}
+ anim_names.sort();
+
+ for( List<PropertyInfo>::Element *E=anim_names.front();E;E=E->next()) {
+ p_list->push_back(E->get());
+ }
{
names.sort();
@@ -204,6 +211,7 @@ void AnimationPlayer::_notification(int p_what) {
if (!get_tree()->is_editor_hint() && animation_set.has(autoplay)) {
play(autoplay);
+ set_autoplay(""); //this line is the fix for autoplay issues with animatio
}
} break;
case NOTIFICATION_PROCESS: {
diff --git a/scene/audio/event_player.cpp b/scene/audio/event_player.cpp
index eabe84a8ee..f43c3c2a59 100644
--- a/scene/audio/event_player.cpp
+++ b/scene/audio/event_player.cpp
@@ -54,6 +54,8 @@ void EventPlayer::set_stream(const Ref<EventStream> &p_stream) {
stream=p_stream;
if (stream.is_valid())
playback=stream->instance_playback();
+ else
+ playback.unref();
if (playback.is_valid()) {
diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp
index f7cfc31b03..c1799ec12c 100644
--- a/scene/audio/stream_player.cpp
+++ b/scene/audio/stream_player.cpp
@@ -100,11 +100,22 @@ void StreamPlayer::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
//set_idle_process(false); //don't annoy
- if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint())
- play();
+ if (stream.is_valid() && !get_tree()->is_editor_hint()) {
+ if (resume_pos>=0) {
+ play(resume_pos);
+ resume_pos=-1;
+ } else if (autoplay) {
+ play();
+ autoplay = false; //this line fix autoplay issues
+ }
+ }
+
} break;
case NOTIFICATION_EXIT_TREE: {
+ if (is_playing()) {
+ resume_pos=get_pos();
+ }
stop(); //wathever it may be doing, stop
} break;
}
@@ -397,6 +408,7 @@ StreamPlayer::StreamPlayer() {
buffering_ms=500;
loop_point=0;
stop_request=false;
+ resume_pos=-1;
}
diff --git a/scene/audio/stream_player.h b/scene/audio/stream_player.h
index 30840137e2..475139c2a4 100644
--- a/scene/audio/stream_player.h
+++ b/scene/audio/stream_player.h
@@ -67,6 +67,7 @@ class StreamPlayer : public Node {
float loop_point;
int buffering_ms;
volatile bool stop_request;
+ float resume_pos;
AudioRBResampler resampler;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 8685ec1c99..f1b910d23f 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -34,7 +34,7 @@
#include "os/input.h"
#include "os/keyboard.h"
-void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color) {
+void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color,float h,float s,float v) {
if (!mat.is_valid())
return;
Ref<Shader> sdr = mat->get_shader();
@@ -44,9 +44,9 @@ void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color) {
mat->set_shader_param("R",p_color.r);
mat->set_shader_param("G",p_color.g);
mat->set_shader_param("B",p_color.b);
- mat->set_shader_param("H",p_color.get_h());
- mat->set_shader_param("S",p_color.get_s());
- mat->set_shader_param("V",p_color.get_v());
+ mat->set_shader_param("H",h);
+ mat->set_shader_param("S",s);
+ mat->set_shader_param("V",v);
mat->set_shader_param("A",p_color.a);
}
@@ -57,14 +57,25 @@ void ColorPicker::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
uv_material->set_shader(get_shader("uv_editor"));
w_material->set_shader(get_shader("w_editor"));
- update_material(uv_material,color);
- update_material(w_material,color);
+ update_material(uv_material,color,h,s,v);
+ update_material(w_material,color,h,s,v);
_update_controls();
} break;
case NOTIFICATION_ENTER_TREE: {
btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
+ update_material(uv_material, color,h,s,v);
+ update_material(w_material, color,h,s,v);
+
+ uv_edit->get_child(0)->cast_to<Control>()->update();
+ w_edit->get_child(0)->cast_to<Control>()->update();
+ _update_color();
}
+
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ c_text->call_deferred("grab_focus");
+ c_text->call_deferred("select");
+ } break;
}
}
@@ -85,11 +96,19 @@ void ColorPicker::_update_controls() {
void ColorPicker::set_color(const Color& p_color) {
color=p_color;
- h=color.get_h();
- s=color.get_s();
- v=color.get_v();
- update_material(uv_material, color);
- update_material(w_material, color);
+ if (color != last_hsv) {
+ h=color.get_h();
+ s=color.get_s();
+ v=color.get_v();
+ last_hsv = color;
+ }
+
+ if (!is_inside_tree())
+ return;
+
+ update_material(uv_material, color,h,s,v);
+ update_material(w_material, color,h,s,v);
+
uv_edit->get_child(0)->cast_to<Control>()->update();
w_edit->get_child(0)->cast_to<Control>()->update();
_update_color();
@@ -100,6 +119,10 @@ void ColorPicker::set_edit_alpha(bool p_show) {
edit_alpha=p_show;
_update_controls();
+
+ if (!is_inside_tree())
+ return;
+
_update_color();
sample->update();
}
@@ -119,12 +142,9 @@ void ColorPicker::_value_changed(double) {
}
color.components[3] = scroll[3]->get_val()/255.0;
- update_material(uv_material,color);
- update_material(w_material,color);
-
- html->set_text(color.to_html(edit_alpha && color.a<1));
+ set_color(color);
- sample->update();
+ c_text->set_text(color.to_html(edit_alpha && color.a<1));
emit_signal("color_changed",color);
@@ -136,6 +156,10 @@ void ColorPicker::_html_entered(const String& p_html) {
return;
color = Color::html(p_html);
+
+ if (!is_inside_tree())
+ return;
+
_update_color();
emit_signal("color_changed",color);
}
@@ -153,7 +177,16 @@ void ColorPicker::_update_color() {
scroll[i]->set_val(color.components[i]*255);
}
- html->set_text(color.to_html(edit_alpha && color.a<1));
+ if (text_is_constructor) {
+ String t = "Color("+String::num(color.r)+","+String::num(color.g)+","+String::num(color.b);
+ if (edit_alpha && color.a<1)
+ t+=(","+String::num(color.a)+")") ;
+ else
+ t+=")";
+ c_text->set_text(t);
+ } else {
+ c_text->set_text(color.to_html(edit_alpha && color.a<1));
+ }
sample->update();
updating=false;
@@ -173,6 +206,21 @@ void ColorPicker::_update_presets()
preset->set_texture(t);
}
+void ColorPicker::_text_type_toggled()
+{
+ if (!get_tree()->is_editor_hint())
+ return;
+ text_is_constructor = !text_is_constructor;
+ if (text_is_constructor) {
+ text_type->set_text("");
+ text_type->set_icon(get_icon("Script", "EditorIcons"));
+ } else {
+ text_type->set_text("#");
+ text_type->set_icon(NULL);
+ }
+ _update_color();
+}
+
Color ColorPicker::get_color() const {
return color;
@@ -199,6 +247,9 @@ void ColorPicker::set_raw_mode(bool p_enabled) {
if (btn_mode->is_pressed()!=p_enabled)
btn_mode->set_pressed(p_enabled);
+ if (!is_inside_tree())
+ return;
+
_update_controls();
_update_color();
}
@@ -217,15 +268,17 @@ void ColorPicker::_hsv_draw(int p_wich,Control* c)
if (!c)
return;
if (p_wich==0) {
- int x=c->get_size().x*color.get_s();
- int y=c->get_size().y-c->get_size().y*color.get_v();
- c->draw_line(Point2(x,0),Point2(x,c->get_size().y),color.inverted());
- c->draw_line(Point2(0,y),Point2(c->get_size().x,y),color.inverted());
+ int x=c->get_size().x*s;
+ int y=c->get_size().y-c->get_size().y*v;
+ Color col = color;
+ col.a=1;
+ c->draw_line(Point2(x,0),Point2(x,c->get_size().y),col.inverted());
+ c->draw_line(Point2(0,y),Point2(c->get_size().x,y),col.inverted());
c->draw_line(Point2(x,y),Point2(x,y),Color(1,1,1),2);
} else if (p_wich==1) {
- int y=c->get_size().y-c->get_size().y*color.get_h();
+ int y=c->get_size().y-c->get_size().y*h;
Color col=Color();
- col.set_hsv(color.get_h(),1,1);
+ col.set_hsv(h,1,1);
c->draw_line(Point2(0,y),Point2(c->get_size().x,y),col.inverted());
}
}
@@ -240,6 +293,7 @@ void ColorPicker::_uv_input(const InputEvent &ev) {
s=x/256;
v=1.0-y/256.0;
color.set_hsv(h,s,v,color.a);
+ last_hsv = color;
set_color(color);
_update_color();
emit_signal("color_changed", color);
@@ -255,6 +309,7 @@ void ColorPicker::_uv_input(const InputEvent &ev) {
s=x/256;
v=1.0-y/256.0;
color.set_hsv(h,s,v,color.a);
+ last_hsv = color;
set_color(color);
_update_color();
emit_signal("color_changed", color);
@@ -272,6 +327,7 @@ void ColorPicker::_w_input(const InputEvent &ev) {
changing_color = false;
}
color.set_hsv(h,s,v,color.a);
+ last_hsv = color;
set_color(color);
_update_color();
emit_signal("color_changed", color);
@@ -282,6 +338,7 @@ void ColorPicker::_w_input(const InputEvent &ev) {
float y = CLAMP((float)bev.y,0,256);
h=1.0-y/256.0;
color.set_hsv(h,s,v,color.a);
+ last_hsv = color;
set_color(color);
_update_color();
emit_signal("color_changed", color);
@@ -364,6 +421,7 @@ void ColorPicker::_bind_methods() {
ObjectTypeDB::bind_method(_MD("add_preset"), &ColorPicker::add_preset);
ObjectTypeDB::bind_method(_MD("_value_changed"),&ColorPicker::_value_changed);
ObjectTypeDB::bind_method(_MD("_html_entered"),&ColorPicker::_html_entered);
+ ObjectTypeDB::bind_method(_MD("_text_type_toggled"),&ColorPicker::_text_type_toggled);
ObjectTypeDB::bind_method(_MD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed);
ObjectTypeDB::bind_method(_MD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed);
ObjectTypeDB::bind_method(_MD("_sample_draw"),&ColorPicker::_sample_draw);
@@ -381,6 +439,7 @@ ColorPicker::ColorPicker() :
updating=true;
edit_alpha=true;
+ text_is_constructor = false;
raw_mode_enabled=false;
changing_color=false;
screen=NULL;
@@ -490,18 +549,20 @@ ColorPicker::ColorPicker() :
btn_mode->connect("toggled", this, "set_raw_mode");
hhb->add_child(btn_mode);
vbr->add_child(hhb);
- html_num = memnew( Label );
- hhb->add_child(html_num);
+ text_type = memnew( Button );
+ text_type->set_flat(true);
+ text_type->connect("pressed", this, "_text_type_toggled");
+ hhb->add_child(text_type);
- html = memnew( LineEdit );
- hhb->add_child(html);
- html->connect("text_entered",this,"_html_entered");
- html_num->set_text("#");
- html->set_h_size_flags(SIZE_EXPAND_FILL);
+ c_text = memnew( LineEdit );
+ hhb->add_child(c_text);
+ c_text->connect("text_entered",this,"_html_entered");
+ text_type->set_text("#");
+ c_text->set_h_size_flags(SIZE_EXPAND_FILL);
_update_controls();
- _update_color();
+ //_update_color();
updating=false;
uv_material.instance();
@@ -564,6 +625,8 @@ void ColorPickerButton::pressed() {
popup->set_pos(get_global_pos()-Size2(0,ms.height));
popup->set_size(ms);
popup->popup();
+
+
}
void ColorPickerButton::_notification(int p_what) {
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index c6c7fe537d..4559bc7391 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -62,22 +62,25 @@ private:
HSlider *scroll[4];
SpinBox *values[4];
Label *labels[4];
- Label *html_num;
- LineEdit *html;
+ Button *text_type;
+ LineEdit *c_text;
bool edit_alpha;
Size2i ms;
+ bool text_is_constructor;
Color color;
bool raw_mode_enabled;
bool updating;
bool changing_color;
float h,s,v;
+ Color last_hsv;
void _html_entered(const String& p_html);
void _value_changed(double);
void _update_controls();
void _update_color();
void _update_presets();
+ void _text_type_toggled();
void _sample_draw();
void _hsv_draw(int p_wich,Control *c);
@@ -87,6 +90,7 @@ private:
void _screen_input(const InputEvent& p_input);
void _add_preset_pressed();
void _screen_pick_pressed();
+
protected:
void _notification(int);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 71a0f50240..af3b37bec2 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -85,9 +85,14 @@ Size2 Control::edit_get_minimum_size() const {
void Control::edit_set_rect(const Rect2& p_edit_rect) {
- Rect2 new_rect=get_rect();
+ Matrix32 postxf;
+ postxf.set_rotation_and_scale(data.rotation,data.scale);
+ Vector2 new_pos = postxf.xform(p_edit_rect.pos);
+
+ Vector2 pos = get_pos()+new_pos;
- new_rect.pos+=p_edit_rect.pos.snapped(Vector2(1,1));
+ Rect2 new_rect=get_rect();
+ new_rect.pos=pos.snapped(Vector2(1,1));
new_rect.size=p_edit_rect.size.snapped(Vector2(1,1));
set_pos(new_rect.pos);
@@ -1597,7 +1602,9 @@ bool Control::has_focus() const {
void Control::grab_focus() {
- ERR_FAIL_COND(!is_inside_tree());
+ if (!is_inside_tree()){
+ ERR_FAIL_COND(!is_inside_tree());
+ }
if (data.focus_mode==FOCUS_NONE)
return;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 9472c589ca..c9c9dbd1d2 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -4,6 +4,12 @@
#include "scene/gui/box_container.h"
+#define ZOOM_SCALE 1.2
+
+#define MIN_ZOOM (((1/ZOOM_SCALE)/ZOOM_SCALE)/ZOOM_SCALE)
+#define MAX_ZOOM (1*ZOOM_SCALE*ZOOM_SCALE*ZOOM_SCALE)
+
+
bool GraphEditFilter::has_point(const Point2& p_point) const {
return ge->_filter_input(p_point);
@@ -85,9 +91,10 @@ void GraphEdit::_update_scroll_offset() {
if (!gn)
continue;
- Point2 pos=gn->get_offset();
+ Point2 pos=gn->get_offset()*zoom;
pos-=Point2(h_scroll->get_val(),v_scroll->get_val());
gn->set_pos(pos);
+ gn->set_scale(Vector2(zoom,zoom));
}
}
@@ -106,8 +113,8 @@ void GraphEdit::_update_scroll() {
continue;
Rect2 r;
- r.pos=gn->get_offset();
- r.size=gn->get_size();
+ r.pos=gn->get_offset()*zoom;
+ r.size=gn->get_size()*zoom;
screen = screen.merge(r);
}
@@ -193,10 +200,11 @@ void GraphEdit::_notification(int p_what) {
h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height);
h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
- zoom_icon->set_texture( get_icon("Zoom", "EditorIcons"));
+// zoom_icon->set_texture( get_icon("Zoom", "EditorIcons"));
}
if (p_what==NOTIFICATION_DRAW) {
+ draw_style_box( get_stylebox("bg"),Rect2(Point2(),get_size()) );
VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true);
}
@@ -516,7 +524,7 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
for(int i=get_child_count()-1;i>=0;i--) {
GraphNode *gn=get_child(i)->cast_to<GraphNode>();
if (gn && gn->is_selected())
- gn->set_offset(gn->get_drag_from()+drag_accum);
+ gn->set_offset((gn->get_drag_from()*zoom+drag_accum)/zoom);
}
}
@@ -650,6 +658,8 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
} else {
if (_filter_input(Vector2(b.x,b.y)))
return;
+ if (Input::get_singleton()->is_key_pressed(KEY_SPACE))
+ return;
box_selecting = true;
box_selecting_from = get_local_mouse_pos();
@@ -697,11 +707,13 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
}
if (b.button_index==BUTTON_WHEEL_UP && b.pressed) {
- sl_zoom->set_val(zoom/0.9);
+ //too difficult to get right
+ //set_zoom(zoom*ZOOM_SCALE);
}
if (b.button_index==BUTTON_WHEEL_DOWN && b.pressed) {
- sl_zoom->set_val(zoom*0.9);
+ //too difficult to get right
+ //set_zoom(zoom/ZOOM_SCALE);
}
}
@@ -725,21 +737,29 @@ void GraphEdit::clear_connections() {
void GraphEdit::set_zoom(float p_zoom) {
- if (p_zoom<0.01) p_zoom=0.01;
- if (p_zoom>4) p_zoom=4;
+ p_zoom=CLAMP(p_zoom,MIN_ZOOM,MAX_ZOOM);
if (zoom == p_zoom)
return;
+ zoom_minus->set_disabled(zoom==MIN_ZOOM);
+ zoom_plus->set_disabled(zoom==MAX_ZOOM);
+
+ Vector2 sbofs = (Vector2( h_scroll->get_val(), v_scroll->get_val() ) + get_size()/2)/zoom;
+
float prev_zoom = zoom;
zoom = p_zoom;
- for (int i = 0; i < get_child_count(); i++) {
- GraphNode *child = get_child(i)->cast_to<GraphNode>();
- if (!child)
- continue;
- Point2 ofs = child->get_offset() / prev_zoom * zoom;
- child->set_scale(Vector2(zoom,zoom));
- child->set_offset(ofs);
+ top_layer->update();
+
+ _update_scroll();
+
+ if (is_visible()) {
+
+ Vector2 ofs = sbofs*zoom - get_size()/2;
+ h_scroll->set_val( ofs.x );
+ v_scroll->set_val( ofs.y );
}
+
+
update();
}
@@ -772,6 +792,26 @@ Array GraphEdit::_get_connection_list() const {
}
return arr;
}
+
+
+
+void GraphEdit::_zoom_minus() {
+
+
+ set_zoom(zoom/ZOOM_SCALE);
+}
+void GraphEdit::_zoom_reset() {
+
+
+ set_zoom(1);
+}
+
+void GraphEdit::_zoom_plus() {
+
+ set_zoom(zoom*ZOOM_SCALE);
+}
+
+
void GraphEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node);
@@ -792,6 +832,9 @@ void GraphEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input);
ObjectTypeDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw);
ObjectTypeDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved);
+ ObjectTypeDB::bind_method(_MD("_zoom_minus"),&GraphEdit::_zoom_minus);
+ ObjectTypeDB::bind_method(_MD("_zoom_reset"),&GraphEdit::_zoom_reset);
+ ObjectTypeDB::bind_method(_MD("_zoom_plus"),&GraphEdit::_zoom_plus);
ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event);
@@ -837,18 +880,25 @@ GraphEdit::GraphEdit() {
zoom = 1;
- HBoxContainer* tools = memnew( HBoxContainer );
- add_child(tools);
+ HBoxContainer *zoom_hb = memnew( HBoxContainer );
+ top_layer->add_child(zoom_hb);
+ zoom_hb->set_pos(Vector2(10,10));
+
+
+ zoom_minus = memnew( ToolButton );
+ zoom_hb->add_child(zoom_minus);
+ zoom_minus->connect("pressed",this,"_zoom_minus");
+ zoom_minus->set_icon(get_icon("minus"));
+
+ zoom_reset = memnew( ToolButton );
+ zoom_hb->add_child(zoom_reset);
+ zoom_reset->connect("pressed",this,"_zoom_reset");
+ zoom_reset->set_icon(get_icon("reset"));
+
+ zoom_plus = memnew( ToolButton );
+ zoom_hb->add_child(zoom_plus);
+ zoom_plus->connect("pressed",this,"_zoom_plus");
+ zoom_plus->set_icon(get_icon("more"));
- zoom_icon = memnew( TextureFrame );
- tools->add_child(zoom_icon);
- sl_zoom = memnew( HSlider );
- sl_zoom->set_min(0.01);
- sl_zoom->set_max(4);
- sl_zoom->set_val(1);
- sl_zoom->set_step(0.01);
- sl_zoom->connect("value_changed", this, "set_zoom");
- tools->add_child(sl_zoom);
- sl_zoom->set_custom_minimum_size(Size2(200,0));
}
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index fe9c36cee4..a189c10046 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -4,7 +4,9 @@
#include "scene/gui/graph_node.h"
#include "scene/gui/scroll_bar.h"
#include "scene/gui/slider.h"
+#include "scene/gui/tool_button.h"
#include "texture_frame.h"
+
class GraphEdit;
class GraphEditFilter : public Control {
@@ -35,8 +37,15 @@ public:
};
private:
- TextureFrame* zoom_icon;
- HSlider* sl_zoom;
+
+ ToolButton *zoom_minus;
+ ToolButton *zoom_reset;
+ ToolButton *zoom_plus;
+
+ void _zoom_minus();
+ void _zoom_reset();
+ void _zoom_plus();
+
HScrollBar* h_scroll;
VScrollBar* v_scroll;
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 762afb158a..eef1bf79c4 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -591,4 +591,5 @@ void GraphNode::_bind_methods() {
GraphNode::GraphNode() {
show_close=false;
connpos_dirty=true;
+ set_stop_mouse(false);
}
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index f035cb7722..2d2cabfc01 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -826,22 +826,25 @@ void ItemList::_notification(int p_what) {
if (current_columns==1) {
rcache.size.width = width-rcache.pos.x;
}
- if (items[i].custom_bg.a>0.001) {
- Rect2 r=rcache;
- r.pos+=base_ofs;
- draw_rect(r,items[i].custom_bg);
- }
- if (items[i].selected) {
- Rect2 r=rcache;
- r.pos+=base_ofs;
- r.pos.x-=sbsel->get_margin(MARGIN_LEFT);
- r.size.x+=sbsel->get_margin(MARGIN_LEFT)+sbsel->get_margin(MARGIN_RIGHT);
- r.pos.y-=sbsel->get_margin(MARGIN_TOP);
- r.size.y+=sbsel->get_margin(MARGIN_TOP)+sbsel->get_margin(MARGIN_BOTTOM);
+ Rect2 r=rcache;
+ r.pos+=base_ofs;
- draw_style_box(sbsel,r);
+ // Use stylebox to dimension potential bg color, even if not selected
+ r.pos.x-=sbsel->get_margin(MARGIN_LEFT);
+ r.size.x+=sbsel->get_margin(MARGIN_LEFT)+sbsel->get_margin(MARGIN_RIGHT);
+ r.pos.y-=sbsel->get_margin(MARGIN_TOP);
+ r.size.y+=sbsel->get_margin(MARGIN_TOP)+sbsel->get_margin(MARGIN_BOTTOM);
+ if (items[i].selected) {
+ draw_style_box(sbsel,r);
+ }
+ if (items[i].custom_bg.a>0.001) {
+ r.pos.x+=2;
+ r.size.x-=4;
+ r.pos.y+=2;
+ r.size.y-=4;
+ draw_rect(r,items[i].custom_bg);
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index fdced3f62f..2a62ab30fc 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -80,8 +80,8 @@ void LineEdit::_input_event(InputEvent p_event) {
selection.creating=false;
selection.doubleclick=false;
- // notify to show soft keyboard
- notification(NOTIFICATION_FOCUS_ENTER);
+ if (OS::get_singleton()->has_virtual_keyboard())
+ OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect());
}
update();
@@ -230,8 +230,9 @@ void LineEdit::_input_event(InputEvent p_event) {
case KEY_RETURN: {
emit_signal( "text_entered",text );
- // notify to hide soft keyboard
- notification(NOTIFICATION_FOCUS_EXIT);
+ if (OS::get_singleton()->has_virtual_keyboard())
+ OS::get_singleton()->hide_virtual_keyboard();
+
return;
} break;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index ecce71bdbd..c3e75842c3 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -633,7 +633,6 @@ int Tabs::get_tab_width(int p_idx) const {
x+=tab_bg->get_minimum_size().width;
if (tabs[p_idx].right_button.is_valid()) {
- print_line("has right");
Ref<Texture> rb=tabs[p_idx].right_button;
Size2 bms = rb->get_size();//+get_stylebox("button")->get_minimum_size();
bms.width+=get_constant("hseparation");
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7f7c8c023c..bf012b7a03 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1197,6 +1197,12 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (mb.button_index==BUTTON_WHEEL_DOWN) {
v_scroll->set_val( v_scroll->get_val() +3 );
}
+ if (mb.button_index==BUTTON_WHEEL_LEFT) {
+ h_scroll->set_val( h_scroll->get_val() -3 );
+ }
+ if (mb.button_index==BUTTON_WHEEL_RIGHT) {
+ h_scroll->set_val( h_scroll->get_val() +3 );
+ }
if (mb.button_index==BUTTON_LEFT) {
int row,col;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index e81c08dbea..05b1e8bcea 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -482,7 +482,7 @@ void TreeItem::deselect(int p_column) {
_cell_deselected(p_column);
}
-void TreeItem::add_button(int p_column,const Ref<Texture>& p_button,int p_id) {
+void TreeItem::add_button(int p_column, const Ref<Texture>& p_button, int p_id, bool p_disabled) {
ERR_FAIL_INDEX( p_column, cells.size() );
@@ -492,6 +492,7 @@ void TreeItem::add_button(int p_column,const Ref<Texture>& p_button,int p_id) {
if (p_id<0)
p_id=cells[p_column].buttons.size();
button.id=p_id;
+ button.disabled=p_disabled;
cells[p_column].buttons.push_back(button);
_changed_notify(p_column);
}
@@ -533,6 +534,15 @@ int TreeItem::get_button_by_id(int p_column,int p_id) const {
return -1;
}
+
+bool TreeItem::is_button_disabled(int p_column, int p_idx) const {
+
+ ERR_FAIL_INDEX_V( p_column, cells.size(), false );
+ ERR_FAIL_INDEX_V( p_idx, cells[p_column].buttons.size(), false );
+
+ return cells[p_column].buttons[p_idx].disabled;
+
+}
void TreeItem::set_button(int p_column,int p_idx,const Ref<Texture>& p_button){
ERR_FAIL_COND( p_button.is_null() );
@@ -672,10 +682,11 @@ void TreeItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color);
ObjectTypeDB::bind_method(_MD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color);
- ObjectTypeDB::bind_method(_MD("add_button","column","button:Texture","button_idx"),&TreeItem::add_button);
+ ObjectTypeDB::bind_method(_MD("add_button","column","button:Texture","button_idx","disabled"),&TreeItem::add_button,DEFVAL(-1),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_button_count","column"),&TreeItem::get_button_count);
ObjectTypeDB::bind_method(_MD("get_button:Texture","column","button_idx"),&TreeItem::get_button);
ObjectTypeDB::bind_method(_MD("erase_button","column","button_idx"),&TreeItem::erase_button);
+ ObjectTypeDB::bind_method(_MD("is_button_disabled","column","button_idx"),&TreeItem::is_button_disabled);
ObjectTypeDB::bind_method(_MD("set_tooltip","column","tooltip"),&TreeItem::set_tooltip);
ObjectTypeDB::bind_method(_MD("get_tooltip","column"),&TreeItem::get_tooltip);
@@ -1015,14 +1026,15 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
Point2i o = Point2i( ofs+w-s.width, p_pos.y )-cache.offset+p_draw_ofs;
- if (cache.click_type==Cache::CLICK_BUTTON && cache.click_item==p_item && cache.click_column==i) {
+ if (cache.click_type==Cache::CLICK_BUTTON && cache.click_item==p_item && cache.click_column==i && !p_item->cells[i].buttons[j].disabled) {
//being pressed
cache.button_pressed->draw(get_canvas_item(),Rect2(o,s));
}
o.y+=(label_h-s.height)/2;
o+=cache.button_pressed->get_offset();
- b->draw(ci,o);
+
+ b->draw(ci,o,p_item->cells[i].buttons[j].disabled?Color(1,1,1,0.5):Color(1,1,1,1));
w-=s.width+cache.button_margin;
bw+=s.width+cache.button_margin;
}
@@ -1472,7 +1484,13 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
for(int j=c.buttons.size()-1;j>=0;j--) {
Ref<Texture> b=c.buttons[j].texture;
int w = b->get_size().width + cache.button_pressed->get_minimum_size().width;
+
if (x>col_width-w) {
+ if (c.buttons[j].disabled) {
+ pressed_button=-1;
+ cache.click_type=Cache::CLICK_NONE;
+ return -1;
+ }
pressed_button=j;
cache.click_type=Cache::CLICK_BUTTON;
cache.click_index=j;
@@ -1730,6 +1748,8 @@ void Tree::_text_editor_modal_close() {
return;
}
+ if (value_editor->has_point(value_editor->get_local_mouse_pos()))
+ return;
text_editor_enter(text_editor->get_text());
}
@@ -2316,7 +2336,7 @@ bool Tree::edit_selected() {
return false;
Rect2 rect;
- rect.pos.y = get_item_offset(s) - v_scroll->get_val();
+ rect.pos.y = get_item_offset(s) - get_scroll().y;
for(int i=0;i<col;i++) {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index e4d349978c..e5c95b4d66 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -86,8 +86,9 @@ friend class Tree;
struct Button {
int id;
+ bool disabled;
Ref<Texture> texture;
- Button() { id=0; }
+ Button() { id=0; disabled=false; }
};
Vector< Button > buttons;
@@ -172,12 +173,13 @@ public:
void set_icon_max_width(int p_column,int p_max);
int get_icon_max_width(int p_column) const;
- void add_button(int p_column,const Ref<Texture>& p_button,int p_id=-1);
+ void add_button(int p_column,const Ref<Texture>& p_button,int p_id=-1,bool p_disabled=false);
int get_button_count(int p_column) const;
Ref<Texture> get_button(int p_column,int p_idx) const;
int get_button_id(int p_column,int p_idx) const;
void erase_button(int p_column,int p_idx);
int get_button_by_id(int p_column,int p_id) const;
+ bool is_button_disabled(int p_column,int p_idx) const;
void set_button(int p_column,int p_idx,const Ref<Texture>& p_button);
/* range works for mode number or mode combo */
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index 517cd414c5..fc7cc0a362 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -393,7 +393,7 @@ void VideoPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&VideoPlayer::set_buffering_msec);
ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&VideoPlayer::get_buffering_msec);
- ObjectTypeDB::bind_method(_MD("get_video_texutre:Texture"), &VideoPlayer::get_video_texture );
+ ObjectTypeDB::bind_method(_MD("get_video_texture:Texture"), &VideoPlayer::get_video_texture );
ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/audio_track",PROPERTY_HINT_RANGE,"0,128,1"), _SCS("set_audio_track"), _SCS("get_audio_track") );
ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"VideoStream"), _SCS("set_stream"), _SCS("get_stream") );
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index 2c23b62b12..a118bc9782 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -42,6 +42,7 @@ void Timer::_notification(int p_what) {
break;
#endif
start();
+ autostart=false;
}
} break;
case NOTIFICATION_PROCESS: {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index a1bfbda1fc..104806d891 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -533,7 +533,7 @@ void Viewport::_notification(int p_what) {
Vector2 point = get_canvas_transform().affine_inverse().xform(pos);
Physics2DDirectSpaceState::ShapeResult res[64];
- int rc = ss2d->intersect_point(point,res,64,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
+ int rc = ss2d->intersect_point(point,res,64,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF,true);
for(int i=0;i<rc;i++) {
if (res[i].collider_id && res[i].collider) {
@@ -855,7 +855,7 @@ void Viewport::_camera_transform_changed_notify() {
#endif
}
-void Viewport::_set_camera(Camera* p_camera) {
+void Viewport::_camera_set(Camera* p_camera) {
#ifndef _3D_DISABLED
@@ -880,6 +880,36 @@ void Viewport::_set_camera(Camera* p_camera) {
#endif
}
+bool Viewport::_camera_add(Camera* p_camera) {
+
+ cameras.insert(p_camera);
+ return cameras.size()==1;
+}
+
+void Viewport::_camera_remove(Camera* p_camera) {
+
+ cameras.erase(p_camera);
+ if (camera==p_camera) {
+ camera=NULL;
+ }
+}
+
+void Viewport::_camera_make_next_current(Camera* p_exclude) {
+
+ for(Set<Camera*>::Element *E=cameras.front();E;E=E->next()) {
+
+ if (p_exclude==E->get())
+ continue;
+ if (!E->get()->is_inside_tree())
+ continue;
+ if (camera!=NULL)
+ return;
+
+ E->get()->make_current();
+
+ }
+}
+
void Viewport::set_transparent_background(bool p_enable) {
@@ -1486,7 +1516,8 @@ Control* Viewport::_gui_find_control(const Point2& p_global) {
CanvasItem *pci = sw->get_parent_item();
if (pci)
xform=pci->get_global_transform_with_canvas();
-
+ else
+ xform=sw->get_canvas_transform();
Control *ret = _gui_find_control_at_pos(sw,p_global,xform,gui.focus_inv_xform);
if (ret)
@@ -1505,6 +1536,8 @@ Control* Viewport::_gui_find_control(const Point2& p_global) {
CanvasItem *pci = sw->get_parent_item();
if (pci)
xform=pci->get_global_transform_with_canvas();
+ else
+ xform=sw->get_canvas_transform();
Control *ret = _gui_find_control_at_pos(sw,p_global,xform,gui.focus_inv_xform);
@@ -1624,7 +1657,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
- Matrix32 parent_xform;
+ //Matrix32 parent_xform;
//if (data.parent_canvas_item)
// parent_xform=data.parent_canvas_item->get_global_transform();
@@ -2177,7 +2210,7 @@ void Viewport::_gui_grab_click_focus(Control *p_control) {
//send unclic
- Point2 click =gui.mouse_focus->get_global_transform().affine_inverse().xform(gui.last_mouse_pos);
+ Point2 click =gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
mb.x=click.x;
mb.y=click.y;
mb.button_index=gui.mouse_focus_button;
@@ -2186,8 +2219,8 @@ void Viewport::_gui_grab_click_focus(Control *p_control) {
gui.mouse_focus=p_control;
- gui.focus_inv_xform=gui.mouse_focus->get_global_transform().affine_inverse();
- click =gui.mouse_focus->get_global_transform().affine_inverse().xform(gui.last_mouse_pos);
+ gui.focus_inv_xform=gui.mouse_focus->get_global_transform_with_canvas().affine_inverse();
+ click =gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
mb.x=click.x;
mb.y=click.y;
mb.button_index=gui.mouse_focus_button;
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index cff729612e..5bf7418ee9 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -264,7 +264,11 @@ friend class Control;
friend class Camera;
void _camera_transform_changed_notify();
- void _set_camera(Camera* p_camera);
+ void _camera_set(Camera* p_camera);
+ bool _camera_add(Camera* p_camera); //true if first
+ void _camera_remove(Camera* p_camera);
+ void _camera_make_next_current(Camera* p_exclude);
+
protected:
void _notification(int p_what);
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index f713b9e979..fb9f66a40a 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -264,8 +264,8 @@ void make_default_theme() {
// ToolButton
Ref<StyleBox> tb_empty = memnew( StyleBoxEmpty );
- tb_empty->set_default_margin(MARGIN_LEFT,8);
- tb_empty->set_default_margin(MARGIN_RIGHT,8);
+ tb_empty->set_default_margin(MARGIN_LEFT,6);
+ tb_empty->set_default_margin(MARGIN_RIGHT,6);
tb_empty->set_default_margin(MARGIN_TOP,4);
tb_empty->set_default_margin(MARGIN_BOTTOM,4);
@@ -884,6 +884,13 @@ void make_default_theme() {
t->set_stylebox("panelf","Panel", tc_sb );
t->set_stylebox("panel","PanelContainer", tc_sb );
+ t->set_icon("minus","GraphEdit", make_icon(icon_zoom_less_png) );
+ t->set_icon("reset","GraphEdit", make_icon(icon_zoom_reset_png) );
+ t->set_icon("more","GraphEdit", make_icon(icon_zoom_more_png) );
+ t->set_stylebox("bg","GraphEdit", make_stylebox( tree_bg_png,4,4,4,5) );
+
+
+
t->set_icon( "logo","Icons", make_icon(logo_png) );
diff --git a/scene/resources/default_theme/icon_zoom_less.png b/scene/resources/default_theme/icon_zoom_less.png
new file mode 100644
index 0000000000..3e50ce0c22
--- /dev/null
+++ b/scene/resources/default_theme/icon_zoom_less.png
Binary files differ
diff --git a/scene/resources/default_theme/icon_zoom_more.png b/scene/resources/default_theme/icon_zoom_more.png
new file mode 100644
index 0000000000..4f2928064c
--- /dev/null
+++ b/scene/resources/default_theme/icon_zoom_more.png
Binary files differ
diff --git a/scene/resources/default_theme/icon_zoom_reset.png b/scene/resources/default_theme/icon_zoom_reset.png
new file mode 100644
index 0000000000..36fafc2037
--- /dev/null
+++ b/scene/resources/default_theme/icon_zoom_reset.png
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 4c440ab99a..6414efa74d 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -214,6 +214,21 @@ static const unsigned char icon_stop_png[]={
};
+static const unsigned char icon_zoom_less_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x2,0x8,0x11,0x19,0x15,0x8e,0xdd,0x4e,0x19,0x0,0x0,0x1,0x25,0x49,0x44,0x41,0x54,0x38,0xcb,0x9d,0x92,0xc1,0x8a,0xc2,0x30,0x10,0x86,0xbf,0x99,0x36,0x94,0xd2,0xaa,0x4,0x5b,0x28,0x78,0xe9,0xfb,0x3f,0x95,0x22,0x78,0x11,0x9,0x4a,0xf,0xb5,0xd8,0x64,0x2f,0xdb,0xec,0xb2,0xad,0xbb,0xae,0xdf,0x29,0xcc,0x64,0xfe,0xfc,0x33,0x19,0xe1,0x13,0xe7,0x1c,0xd6,0x5a,0x2e,0x97,0xb,0xde,0x7b,0x0,0x54,0x95,0xed,0x76,0x1b,0x73,0x4b,0xc8,0x54,0xc,0xd0,0x75,0x1d,0xe3,0x38,0x92,0xa6,0x29,0x0,0x8f,0xc7,0x83,0x24,0x49,0x28,0x8a,0x2,0x11,0x59,0x14,0x91,0xe9,0xb0,0xdf,0xef,0x11,0x11,0xd2,0x34,0x65,0xb7,0xdb,0xc5,0xb,0xa7,0xd3,0x89,0x61,0x18,0x68,0xdb,0x76,0xd1,0x89,0x38,0xe7,0xb8,0xdf,0xef,0xf4,0x7d,0xf,0xc0,0x66,0xb3,0x1,0xc0,0x5a,0x1b,0xb,0x8e,0xc7,0x23,0xc6,0x18,0x9a,0xa6,0x99,0x39,0x50,0x6b,0x2d,0x7d,0xdf,0x53,0x96,0x25,0xab,0xd5,0x2a,0x16,0x7f,0x17,0xc9,0xf3,0x3c,0x3e,0x30,0x13,0x88,0x56,0x44,0x50,0xd5,0xe5,0x3e,0x45,0x78,0x86,0x0,0x1c,0xe,0x7,0x42,0x8,0x81,0x7f,0xd0,0xb6,0xad,0x0,0xa8,0x73,0x8e,0x2c,0xcb,0x78,0x17,0x5,0x16,0x87,0xf3,0xb2,0xc0,0x34,0xa8,0x77,0x91,0xa5,0x4d,0x1c,0xc7,0x11,0x80,0x24,0x49,0xe2,0x26,0x5e,0xaf,0x57,0xb2,0x2c,0xc3,0x18,0x43,0x55,0x55,0xf3,0x5f,0x98,0xa6,0xaf,0xaa,0x18,0x63,0x30,0xc6,0xa0,0x1a,0xd3,0xe4,0x79,0xce,0x30,0xc,0x74,0x5d,0xc7,0xf9,0x7c,0x9e,0x3b,0xf8,0xd,0xe7,0x1c,0x21,0x4,0x6e,0xb7,0x5b,0x8c,0x15,0x45,0x41,0x5d,0xd7,0xaf,0x9,0x3c,0x13,0x29,0xcb,0xf2,0xab,0x85,0xbf,0xb0,0xd6,0x22,0x22,0xac,0xd7,0xeb,0x18,0xf3,0xde,0xbf,0xee,0xe0,0xa7,0x13,0xef,0x3d,0x55,0x55,0xf1,0x1,0x48,0x6e,0x80,0x3e,0x13,0xf0,0x5,0xd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
+static const unsigned char icon_zoom_more_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x2,0x8,0x11,0x19,0x1f,0x6e,0x8,0xa7,0x7,0x0,0x0,0x1,0x23,0x49,0x44,0x41,0x54,0x38,0xcb,0x9d,0x92,0x4d,0xaf,0x82,0x30,0x10,0x45,0xcf,0x8c,0x36,0xe0,0x77,0x1a,0x59,0xb0,0x70,0xe1,0xff,0xff,0x57,0xae,0xd5,0x34,0x10,0x30,0x60,0x68,0xeb,0xe6,0xc1,0xf3,0x9,0x26,0xfa,0xee,0xae,0x69,0xe7,0xcc,0xcc,0xbd,0x15,0x7e,0xe4,0x9c,0xc3,0x5a,0xcb,0xf5,0x7a,0x25,0x84,0x0,0x80,0xaa,0xb2,0xdf,0xef,0x87,0xbb,0x29,0x49,0x5f,0xc,0x50,0x55,0x15,0xde,0x7b,0xe6,0xf3,0x39,0x0,0x5d,0xd7,0x31,0x9b,0xcd,0x58,0xad,0x56,0x88,0xc8,0x24,0x44,0x1,0xac,0xb5,0x14,0x45,0x41,0x8,0x1,0x63,0xc,0x87,0xc3,0x81,0xae,0xeb,0x22,0x10,0xbd,0xf7,0xb1,0x2c,0xcb,0x68,0xad,0x1d,0x1a,0xfd,0x99,0xc0,0x39,0x47,0xdb,0xb6,0x34,0x4d,0x3,0xc0,0x6e,0xb7,0x3,0xa0,0x28,0x8a,0xf8,0xfc,0x30,0x4d,0x53,0xc9,0xf3,0x7c,0x3c,0x81,0xb5,0x96,0xa6,0x69,0x58,0xaf,0xd7,0x6c,0x36,0x1b,0xfa,0x89,0x5e,0xd5,0x37,0x98,0x5c,0x1,0x40,0x44,0x50,0xd5,0xb7,0x66,0xbd,0x93,0x0,0x9c,0x4e,0x27,0x62,0x8c,0xf1,0x9b,0xc2,0xe3,0xf1,0x28,0x0,0xea,0x9c,0x23,0x49,0x12,0xfe,0x2b,0x5,0x98,0x32,0xe7,0x63,0xc0,0xbb,0x78,0xbe,0xf2,0xe0,0xf5,0x27,0x7a,0xef,0xb9,0xdd,0x6e,0xaf,0x9e,0x48,0x92,0x24,0x18,0x63,0xc8,0xb2,0x6c,0x9c,0x42,0xef,0xbe,0xaa,0x62,0x8c,0x19,0x75,0x5a,0x2c,0x16,0xdc,0xef,0x77,0xaa,0xaa,0xe2,0x7c,0x3e,0x8f,0x1,0xcf,0xa0,0xa9,0x28,0x8d,0x31,0xf4,0x41,0xd5,0x75,0x3d,0x40,0xf4,0xe3,0x5d,0x45,0xd8,0x6e,0xb7,0xc3,0xb9,0xae,0x6b,0x2e,0x97,0xcb,0xaf,0x7,0x9f,0xc8,0x39,0x47,0x8c,0x91,0xb2,0x2c,0x1,0x58,0x2e,0x97,0xdf,0x1,0x9e,0x21,0x21,0x4,0xb2,0x2c,0xe3,0x1,0xf3,0xd9,0x85,0xaf,0x46,0x21,0x2f,0x17,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
+static const unsigned char icon_zoom_reset_png[]={
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x2,0x8,0x11,0x1b,0xa,0x31,0xe3,0x21,0x6e,0x0,0x0,0x0,0xd6,0x49,0x44,0x41,0x54,0x38,0xcb,0xa5,0x92,0xc1,0xaa,0x84,0x30,0xc,0x45,0x4f,0xaa,0x20,0xea,0x42,0x8a,0x2e,0x5c,0xf6,0xff,0xbf,0xaa,0x1f,0xa0,0x4,0xc4,0x85,0x82,0xb6,0x6f,0xf3,0x94,0x19,0x47,0x1d,0x66,0xe6,0xac,0x4a,0x93,0x9b,0x26,0xe9,0x15,0xfe,0x51,0x55,0xac,0xb5,0xf4,0x7d,0x4f,0x8,0x1,0x0,0x63,0xc,0x75,0x5d,0xef,0xb1,0x33,0x64,0x13,0x3,0x8c,0xe3,0xc8,0xba,0xae,0xa4,0x69,0xa,0xc0,0xb2,0x2c,0x24,0x49,0x42,0x59,0x96,0x88,0xc8,0x69,0x11,0xd9,0xe,0xde,0x7b,0x80,0x78,0xbc,0xdf,0x70,0xce,0x3d,0xe5,0x38,0xe7,0x4,0x20,0x55,0x55,0xe6,0x79,0x66,0x9a,0xa6,0xc8,0xd,0x87,0x7,0x76,0x8c,0xb5,0xf6,0x4e,0x1c,0x1f,0x44,0xa7,0x39,0x86,0x1f,0x31,0x0,0x22,0x22,0x67,0x73,0x9f,0xec,0xeb,0x25,0xc7,0xa8,0x2a,0x59,0x96,0x7d,0x24,0x7a,0xe9,0xa0,0x6d,0xdb,0xef,0x47,0xb0,0xd6,0xee,0x3e,0x78,0xb3,0xc4,0xeb,0xe,0xac,0xb5,0x54,0x55,0xf5,0xfd,0x12,0xb7,0x22,0x77,0xe4,0x79,0x7e,0x6d,0x65,0xef,0x7d,0xbc,0x8a,0x1d,0xc6,0x39,0xba,0x53,0x7e,0xf2,0x41,0xd7,0x75,0x6f,0xff,0xfe,0x9,0x55,0x25,0xc6,0xc8,0x30,0xc,0x0,0x14,0x45,0xf1,0x59,0x81,0xc7,0x22,0x21,0x4,0x9a,0xa6,0xe1,0xf,0x29,0x54,0x56,0xd3,0x43,0xf4,0x61,0x53,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
+
static const unsigned char line_edit_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x6,0x0,0x0,0x0,0x8d,0x32,0xcf,0xbd,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0xa,0x14,0x3,0x1d,0x2f,0xec,0x8c,0x33,0x2f,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x9d,0x49,0x44,0x41,0x54,0x18,0xd3,0xb5,0x90,0x31,0xe,0xc2,0x40,0x10,0x3,0xed,0xbb,0xd5,0x25,0xa1,0xa1,0x3,0x9,0x41,0xc1,0x33,0x78,0x15,0x5f,0xc8,0x93,0x41,0x14,0x49,0x2e,0xbb,0xb7,0x29,0x2,0x52,0x20,0x14,0x34,0x58,0x72,0x63,0x4f,0x61,0x99,0xfb,0xdd,0xe1,0x9a,0x52,0xd5,0xc6,0x10,0x6b,0x92,0x58,0xca,0xdd,0x61,0xc5,0xfa,0x9c,0x87,0x96,0xa7,0xe3,0xf9,0x56,0xa5,0x7a,0x2b,0x22,0x0,0xde,0x41,0xc0,0xa1,0xaa,0x18,0x72,0x7f,0x97,0x18,0x62,0x23,0x22,0x88,0x22,0xe0,0x7,0xe8,0x70,0x0,0x80,0x6a,0x6c,0x2,0xc9,0x2,0x70,0x5,0x1,0x78,0x66,0x4,0xc9,0x12,0xf0,0xa3,0xfe,0x0,0xba,0x7b,0x98,0x67,0xfb,0xaa,0x9c,0x33,0x87,0xbb,0x7,0xb1,0x62,0x9d,0xaa,0xa6,0xd7,0xfc,0x6f,0xf7,0x58,0xb1,0x3e,0x36,0xf5,0xa6,0x3,0x70,0x29,0x66,0x30,0x53,0x5d,0x5a,0x75,0xd4,0x51,0xc7,0x47,0xce,0x43,0x3b,0x1,0xc,0x2e,0x55,0x5d,0x5f,0x72,0xb6,0x33,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 43196a43d4..a9010e79a2 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -226,7 +226,7 @@ Node *SceneState::instance(bool p_gen_edit_state) const {
node->add_to_group( snames[ n.groups[j] ], true );
}
- if (n.instance>=0 || n.type!=TYPE_INSTANCED) {
+ if (n.instance>=0 || n.type!=TYPE_INSTANCED || i==0) {
//if node was not part of instance, must set it's name, parenthood and ownership
if (i>0) {
if (parent) {
@@ -239,7 +239,6 @@ Node *SceneState::instance(bool p_gen_edit_state) const {
} else {
node->_set_name_nocheck( snames[ n.name ] );
}
-
}
if (n.owner>=0) {
@@ -1317,11 +1316,23 @@ StringName SceneState::get_node_name(int p_idx) const {
return names[nodes[p_idx].name];
}
+
+bool SceneState::is_node_instance_placeholder(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,nodes.size(),false);
+
+ return nodes[p_idx].instance>=0 && nodes[p_idx].instance&FLAG_INSTANCE_IS_PLACEHOLDER;
+
+}
+
Ref<PackedScene> SceneState::get_node_instance(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,nodes.size(),Ref<PackedScene>());
if (nodes[p_idx].instance>=0) {
- return variants[nodes[p_idx].instance];
+ if (nodes[p_idx].instance&FLAG_INSTANCE_IS_PLACEHOLDER)
+ return Ref<PackedScene>();
+ else
+ return variants[nodes[p_idx].instance&FLAG_MASK];
} else if (nodes[p_idx].parent<0 || nodes[p_idx].parent==NO_PARENT_SAVED) {
if (base_scene_idx>=0) {
@@ -1335,6 +1346,19 @@ Ref<PackedScene> SceneState::get_node_instance(int p_idx) const {
}
+
+String SceneState::get_node_instance_placeholder(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,nodes.size(),String());
+
+ if (nodes[p_idx].instance>=0 && nodes[p_idx].instance&FLAG_INSTANCE_IS_PLACEHOLDER) {
+ return variants[nodes[p_idx].instance&FLAG_MASK];
+ }
+
+ return String();
+
+}
+
Vector<StringName> SceneState::get_node_groups(int p_idx) const{
ERR_FAIL_INDEX_V(p_idx,nodes.size(),Vector<StringName>());
Vector<StringName> groups;
@@ -1578,6 +1602,8 @@ void SceneState::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_node_name","idx"),&SceneState::get_node_name);
ObjectTypeDB::bind_method(_MD("get_node_path","idx","for_parent"),&SceneState::get_node_path,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_node_owner_path","idx"),&SceneState::get_node_owner_path);
+ ObjectTypeDB::bind_method(_MD("is_node_instance_placeholder","idx"),&SceneState::is_node_instance_placeholder);
+ ObjectTypeDB::bind_method(_MD("get_node_instance_placeholder","idx"),&SceneState::get_node_instance_placeholder);
ObjectTypeDB::bind_method(_MD("get_node_instance:PackedScene","idx"),&SceneState::get_node_instance);
ObjectTypeDB::bind_method(_MD("get_node_groups","idx"),&SceneState::_get_node_groups);
ObjectTypeDB::bind_method(_MD("get_node_property_count","idx"),&SceneState::get_node_property_count);
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index 7fda4392d8..6a26cc472c 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -48,11 +48,7 @@ class SceneState : public Reference {
int base_scene_idx;
enum {
- FLAG_ID_IS_PATH=(1<<30),
- FLAG_INSTANCE_IS_PLACEHOLDER=(1<<30),
- FLAG_MASK=(1<<24)-1,
NO_PARENT_SAVED=0x7FFFFFFF,
-
};
struct NodeData {
@@ -115,7 +111,10 @@ protected:
public:
enum {
- TYPE_INSTANCED=0x7FFFFFFF
+ FLAG_ID_IS_PATH=(1<<30),
+ TYPE_INSTANCED=0x7FFFFFFF,
+ FLAG_INSTANCE_IS_PLACEHOLDER=(1<<30),
+ FLAG_MASK=(1<<24)-1,
};
static void set_disable_placeholders(bool p_disable);
@@ -148,6 +147,8 @@ public:
NodePath get_node_path(int p_idx,bool p_for_parent=false) const;
NodePath get_node_owner_path(int p_idx) const;
Ref<PackedScene> get_node_instance(int p_idx) const;
+ String get_node_instance_placeholder(int p_idx) const;
+ bool is_node_instance_placeholder(int p_idx) const;
Vector<StringName> get_node_groups(int p_idx) const;
int get_node_property_count(int p_idx) const;
diff --git a/scene/resources/sample.cpp b/scene/resources/sample.cpp
index 4b25a2c490..87fcfc425d 100644
--- a/scene/resources/sample.cpp
+++ b/scene/resources/sample.cpp
@@ -151,8 +151,8 @@ void Sample::set_loop_format(LoopFormat p_format) {
if (sample.is_valid())
AudioServer::get_singleton()->sample_set_loop_format(sample,(AudioServer::SampleLoopFormat)p_format);
loop_format=p_format;
-
}
+
Sample::LoopFormat Sample::get_loop_format() const {
return loop_format;
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index f3dcf16e28..6bd5f520d2 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -170,6 +170,7 @@ Error ResourceInteractiveLoaderText::poll() {
_printerr();
}
+ resource_current++;
return error;
@@ -227,6 +228,8 @@ Error ResourceInteractiveLoaderText::poll() {
}
+ resource_current++;
+
while(true) {
String assign;
@@ -291,6 +294,8 @@ Error ResourceInteractiveLoaderText::poll() {
resource=Ref<Resource>(r);
+ resource_current++;
+
while(true) {
String assign;
@@ -384,6 +389,22 @@ Error ResourceInteractiveLoaderText::poll() {
}
}
+ if (next_tag.fields.has("instance_placeholder")) {
+
+ String path=next_tag.fields["instance_placeholder"];
+
+ int path_v = packed_scene->get_state()->add_value(path);
+
+ if (packed_scene->get_state()->get_node_count()==0) {
+ error=ERR_FILE_CORRUPT;
+ error_text="Instance Placeholder can't be used for inheritance.";
+ _printerr();
+ return error;
+ }
+
+ instance=path_v|SceneState::FLAG_INSTANCE_IS_PLACEHOLDER;
+ }
+
if (next_tag.fields.has("owner")) {
owner=packed_scene->get_state()->add_node_path(next_tag.fields["owner"]);
} else {
@@ -715,6 +736,7 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const
fw->store_8(c);
c=f->get_8();
}
+ f->close();
bool all_ok = fw->get_error()==OK;
@@ -745,6 +767,8 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f,bool p_skip_first_tag)
stream.f=f;
is_scene=false;
+ resource_current=0;
+
VariantParser::Tag tag;
Error err = VariantParser::parse_tag(&stream,lines,error_text,tag);
@@ -1117,7 +1141,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
if (packed_scene.is_valid()) {
//add instances to external resources if saving a packed scene
for(int i=0;i<packed_scene->get_state()->get_node_count();i++) {
- Ref<PackedScene> instance=packed_scene->get_state()->get_node_instance(i);
+ if (packed_scene->get_state()->is_node_instance_placeholder(i))
+ continue;
+
+ Ref<PackedScene> instance=packed_scene->get_state()->get_node_instance(i);
if (instance.is_valid() && !external_resources.has(instance)) {
int index = external_resources.size();
external_resources[instance]=index;
@@ -1261,8 +1288,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
NodePath path = state->get_node_path(i,true);
NodePath owner = state->get_node_owner_path(i);
Ref<PackedScene> instance = state->get_node_instance(i);
+ String instance_placeholder = state->get_node_instance_placeholder(i);
Vector<StringName> groups = state->get_node_groups(i);
+
if (instance.is_valid())
print_line("for path "+String(path)+" instance "+instance->get_path());
@@ -1291,6 +1320,14 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re
f->store_string(header);
+ if (instance_placeholder!=String()) {
+
+ String vars;
+ f->store_string(" instance_placeholder=");
+ VariantWriter::write_to_string(instance_placeholder,vars,_write_resources,this);
+ f->store_string(vars);
+ }
+
if (instance.is_valid()) {
String vars;
diff --git a/servers/audio/audio_server_sw.cpp b/servers/audio/audio_server_sw.cpp
index d634c348dc..8b5b5e4f46 100644
--- a/servers/audio/audio_server_sw.cpp
+++ b/servers/audio/audio_server_sw.cpp
@@ -765,6 +765,8 @@ void AudioServerSW::free(RID p_id) {
void AudioServerSW::_thread_func(void *self) {
+ Thread::set_name("AudioServerSW");
+
AudioServerSW *as=(AudioServerSW *)self;
while (!as->exit_update_thread) {
@@ -807,7 +809,6 @@ void AudioServerSW::init() {
#ifndef NO_THREADS
exit_update_thread=false;
thread = Thread::create(_thread_func,this);
- thread->set_name("AudioServerSW");
#endif
}
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 9ba6bdd5ba..eaf9427ad8 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -46,7 +46,7 @@ _FORCE_INLINE_ static bool _match_object_type_query(CollisionObject2DSW *p_objec
}
-int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,bool p_pick_point) {
if (p_result_max<=0)
return 0;
@@ -69,7 +69,7 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeRes
const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
- if (!col_obj->is_pickable())
+ if (p_pick_point && !col_obj->is_pickable())
continue;
int shape_idx=space->intersection_query_subindex_results[i];
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 2bdbb8a881..5f35f224b2 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -46,7 +46,7 @@ public:
Space2DSW *space;
- virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION, bool p_pick_point=false);
virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 08f69f98b1..7a4365bea3 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -182,7 +182,7 @@ public:
};
- virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
+ virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,bool p_pick_point=false)=0;
virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 4752210b5f..06eaa4d122 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -65,8 +65,8 @@ void register_server_types() {
Globals::get_singleton()->add_singleton( Globals::Singleton("PS",PhysicsServer::get_singleton()) );
Globals::get_singleton()->add_singleton( Globals::Singleton("Physics2DServer",Physics2DServer::get_singleton()) );
Globals::get_singleton()->add_singleton( Globals::Singleton("PS2D",Physics2DServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSoundServer",SpatialSound2DServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("SS",SpatialSound2DServer::get_singleton()) );
+ Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSoundServer",SpatialSoundServer::get_singleton()) );
+ Globals::get_singleton()->add_singleton( Globals::Singleton("SS",SpatialSoundServer::get_singleton()) );
Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSound2DServer",SpatialSound2DServer::get_singleton()) );
Globals::get_singleton()->add_singleton( Globals::Singleton("SS2D",SpatialSound2DServer::get_singleton()) );
diff --git a/tools/SCsub b/tools/SCsub
index f046e9ad08..5613d8a6c9 100644
--- a/tools/SCsub
+++ b/tools/SCsub
@@ -11,7 +11,6 @@ if (env["tools"]!="no"):
SConscript('collada/SCsub');
SConscript('docdump/SCsub');
SConscript('freetype/SCsub');
- SConscript('pe_bliss/SCsub');
SConscript('doc/SCsub')
SConscript('pck/SCsub')
diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp
index 11e4797747..3836fa710b 100644
--- a/tools/doc/doc_data.cpp
+++ b/tools/doc/doc_data.cpp
@@ -433,7 +433,7 @@ void DocData::generate(bool p_basic_types) {
if (i==Variant::INPUT_EVENT) {
static const char* ie_type[InputEvent::TYPE_MAX]={
- "","Key","MouseMotion","MouseButton","JoyMotion","JoyButton","ScreenTouch","ScreenDrag","Action"
+ "","Key","MouseMotion","MouseButton","JoystickMotion","JoystickButton","ScreenTouch","ScreenDrag","Action"
};
cname+=ie_type[j];
}
diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile
new file mode 100644
index 0000000000..428de9d1a7
--- /dev/null
+++ b/tools/docker/Dockerfile
@@ -0,0 +1,13 @@
+FROM ubuntu:14.04
+MAINTAINER Mohammad Rezai, https://github.com/mrezai
+WORKDIR /godot-dev
+COPY scripts/install-android-tools /godot-dev/
+ENV DEBIAN_FRONTEND noninteractive
+RUN dpkg --add-architecture i386 && \
+ apt-get update && \
+ apt-get upgrade -y && \
+ apt-get install --no-install-recommends -y -q \
+ build-essential gcc-multilib g++-multilib mingw32 mingw-w64 scons pkg-config libx11-dev libxcursor-dev \
+ libasound2-dev libfreetype6-dev libgl1-mesa-dev libglu-dev libssl-dev libxinerama-dev libudev-dev \
+ git wget openjdk-7-jdk libbcprov-java libc6:i386 libncurses5:i386 libstdc++6:i386 zlib1g:i386 lib32z1
+
diff --git a/tools/docker/README.md b/tools/docker/README.md
new file mode 100644
index 0000000000..7f10b46ad8
--- /dev/null
+++ b/tools/docker/README.md
@@ -0,0 +1,40 @@
+## A Docker image to build Linux, Windows and Android godot binaries.
+
+The main reason to write this, is to provide a simple way in all platforms to integrate external godot modules and build a custom version of godot.
+
+## usage
+1. Install docker on Linux or docker toolbox on Windows or Mac.
+2. Open a terminal on linux or "Docker Quickstart Terminal" on Windows or Mac.
+3. Run command:
+ - Linux: `cd`
+ - Windows: `cd /c/Users/YOUR_USERNAME`
+ - Mac: `cd /Users/YOUR_USERNAME`
+4. Get godot source code: `git clone https://github.com/godotengine/godot.git`
+5. Run command: `cd godot/tools/docker`
+6. Run command: `docker build -t godot .`(In Linux run Docker commands with `sudo` or add your user to docker group before run the Docker commands). The godot docker image will be build after a while.
+7. Run command:
+ - Linux: `docker run -it --name=godot-dev -v /home/YOUR_USERNAME/godot:/godot-dev/godot godot`
+ - Windows: `docker run -it --name=godot-dev -v /c/Users/YOUR_USERNAME/godot:/godot-dev/godot godot`
+ - Mac: `docker run -it --name=godot-dev -v /Users/YOUR_USERNAME/godot:/godot-dev/godot godot`
+ You are in the godot-dev container and /godot-dev directory now.
+8. Run `./install-android-tools` to download and install all android development tools.
+9. Run command: `source ~/.bashrc`
+10. Run command: `cd godot`
+11. Run command: `scons p=android target=release` to test everything is ok. You can set platform to x11, windows, android, haiku and server.
+
+After use and exit, you can use this environment again by open terminal and type commands: `docker start godot-dev && docker attach godot-dev`.
+
+### Windows and Mac stuffs:
+
+- Speed up compilation:
+ - Exit from container.
+ - Run command: `docker-machine stop`
+ - Open "Oracle VM VirtualBox".
+ - In settings of default VM increase CPU cores and RAM to suitable values.
+ - Run command: `docker-machine start`
+ - Run command: `docker start godot-dev && docker attach godot-dev`
+
+- ssh to VM(can be useful sometimes):
+ - `docker-machine ssh`
+
+Check docker and boot2docker projects for more details.
diff --git a/tools/docker/scripts/install-android-tools b/tools/docker/scripts/install-android-tools
new file mode 100644
index 0000000000..8a617d9942
--- /dev/null
+++ b/tools/docker/scripts/install-android-tools
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+BASH_RC=~/.bashrc
+GODOT_BUILD_TOOLS_PATH=/godot-dev/build-tools
+mkdir -p $GODOT_BUILD_TOOLS_PATH
+cd $GODOT_BUILD_TOOLS_PATH
+
+ANDROID_BASE_URL=http://dl.google.com/android
+
+ANDROID_SDK_RELEASE=android-sdk_r24.4.1
+ANDROID_SDK_DIR=android-sdk-linux
+ANDROID_SDK_FILENAME=$ANDROID_SDK_RELEASE-linux.tgz
+ANDROID_SDK_URL=$ANDROID_BASE_URL/$ANDROID_SDK_FILENAME
+ANDROID_SDK_PATH=$GODOT_BUILD_TOOLS_PATH/$ANDROID_SDK_DIR
+ANDROID_SDK_SHA1=725bb360f0f7d04eaccff5a2d57abdd49061326d
+
+ANDROID_NDK_RELEASE=android-ndk-r10e
+ANDROID_NDK_DIR=$ANDROID_NDK_RELEASE
+ANDROID_NDK_FILENAME=$ANDROID_NDK_RELEASE-linux-x86_64.bin
+ANDROID_NDK_URL=$ANDROID_BASE_URL/ndk/$ANDROID_NDK_FILENAME
+ANDROID_NDK_PATH=$GODOT_BUILD_TOOLS_PATH/$ANDROID_NDK_DIR
+ANDROID_NDK_MD5=19af543b068bdb7f27787c2bc69aba7f
+
+echo
+echo "Download and install Android development tools ..."
+echo
+
+if [ ! -e $ANDROID_SDK_FILENAME ]; then
+ echo "Downloading: Android SDK ..."
+ wget $ANDROID_SDK_URL
+else
+ echo $ANDROID_SDK_SHA1 $ANDROID_SDK_FILENAME > $ANDROID_SDK_FILENAME.sha1
+ sha1sum --check --strict $ANDROID_SDK_FILENAME.sha1
+ if [ ! $? -eq 0 ]; then
+ echo "Downloading: Android SDK ..."
+ wget $ANDROID_SDK_URL
+ fi
+fi
+
+if [ ! -d $ANDROID_SDK_DIR ]; then
+ tar -xvzf $ANDROID_SDK_FILENAME
+fi
+
+if [ ! -e $ANDROID_NDK_FILENAME ]; then
+ echo "Downloading: Android NDK ..."
+ wget $ANDROID_NDK_URL
+else
+ echo $ANDROID_NDK_MD5 $ANDROID_NDK_FILENAME > $ANDROID_NDK_FILENAME.md5
+ md5sum --check --strict $ANDROID_NDK_FILENAME.md5
+ if [ ! $? -eq 0 ]; then
+ echo "Downloading: Android NDK ..."
+ wget $ANDROID_NDK_URL
+ fi
+fi
+
+if [ ! -d $ANDROID_NDK_DIR ]; then
+ chmod a+x $ANDROID_NDK_FILENAME
+ ./$ANDROID_NDK_FILENAME
+ echo
+fi
+
+cd $ANDROID_SDK_DIR/tools
+chmod a+x android
+
+if ! ./android list target | grep -q 'android-19'; then
+ echo "Installing: Android Tools ..."
+ echo y | ./android update sdk --no-ui --all --filter "platform-tools,android-19,build-tools-19.1.0,\
+ extra-android-m2repository,extra-android-support,extra-google-google_play_services,extra-google-m2repository,\
+ extra-google-play_apk_expansion,extra-google-play_billing,extra-google-play_licensing"
+fi
+
+EXPORT_VAL="export ANDROID_HOME=$ANDROID_SDK_PATH"
+if ! grep -q "^$EXPORT_VAL" $BASH_RC; then
+ echo $EXPORT_VAL >> ~/.bashrc
+fi
+
+
+EXPORT_VAL="export ANDROID_NDK_ROOT=$ANDROID_NDK_PATH"
+if ! grep -q "^$EXPORT_VAL" $BASH_RC; then
+ echo $EXPORT_VAL >> ~/.bashrc
+fi
+
+EXPORT_VAL="export PATH=$PATH:$ANDROID_SDK_PATH/tools"
+if ! grep -q "^export PATH=.*$ANDROID_SDK_PATH/tools.*" $BASH_RC; then
+ echo $EXPORT_VAL >> ~/.bashrc
+fi
+
+echo
+echo "Done!"
+echo \ No newline at end of file
diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp
index cdce910665..668a135bc8 100644
--- a/tools/editor/animation_editor.cpp
+++ b/tools/editor/animation_editor.cpp
@@ -35,6 +35,7 @@
#include "scene/gui/separator.h"
#include "editor_node.h"
#include "tools/editor/plugins/animation_player_editor_plugin.h"
+#include "scene/main/viewport.h"
/* Missing to fix:
*Set
@@ -256,6 +257,28 @@ public:
//PopupDialog *ke_dialog;
+ void _fix_node_path(Variant &value) {
+
+
+ NodePath np=value;
+
+ if (np==NodePath())
+ return;
+
+ Node* root = EditorNode::get_singleton()->get_tree()->get_root();
+
+ Node* np_node = root->get_node(np);
+ ERR_FAIL_COND(!np_node);
+
+ Node* edited_node = root->get_node(base);
+ ERR_FAIL_COND(!edited_node);
+
+
+
+ value = edited_node->get_path_to(np_node);
+ }
+
+
void _update_obj(const Ref<Animation> &p_anim) {
if (setting)
return;
@@ -356,10 +379,18 @@ public:
case Animation::TYPE_VALUE: {
if (name=="value") {
+
+ Variant value = p_value;
+
+ if (value.get_type()==Variant::NODE_PATH) {
+
+ _fix_node_path(value);
+ }
+
setting=true;
undo_redo->create_action("Anim Change Value",true);
Variant prev = animation->track_get_key_value(track,key);
- undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,p_value);
+ undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,value);
undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,prev);
undo_redo->add_do_method(this,"_update_obj",animation);
undo_redo->add_undo_method(this,"_update_obj",animation);
@@ -420,7 +451,14 @@ public:
}
if (what=="value") {
- args[idx]=p_value;
+
+ Variant value=p_value;
+ if (value.get_type()==Variant::NODE_PATH) {
+
+ _fix_node_path(value);
+ }
+
+ args[idx]=value;
d_new["args"]=args;
mergeable=true;
}
@@ -441,7 +479,7 @@ public:
} break;
}
- return false;
+
return false;
@@ -616,6 +654,7 @@ public:
float key_ofs;
PropertyInfo hint;
+ NodePath base;
void notify_change() {
@@ -1630,8 +1669,9 @@ void AnimationKeyEditor::_select_at_anim(const Ref<Animation>& p_anim,int p_trac
}
-PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) {
+PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx,NodePath& r_base_path) {
+ r_base_path=NodePath();
ERR_FAIL_COND_V(!animation.is_valid(),PropertyInfo());
ERR_FAIL_INDEX_V(p_idx,animation->get_track_count(),PropertyInfo());
@@ -1640,9 +1680,6 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) {
NodePath path = animation->track_get_path(p_idx);
- String property = path.get_property();
- if (property=="")
- return PropertyInfo();
if (!root->has_node_and_resource(path))
return PropertyInfo();
@@ -1650,6 +1687,15 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) {
RES res;
Node *node = root->get_node_and_resource(path,res);
+
+ if (node) {
+ r_base_path=node->get_path();
+ }
+
+ String property = path.get_property();
+ if (property=="")
+ return PropertyInfo();
+
List<PropertyInfo> pinfo;
if (res.is_valid())
res->get_property_list(&pinfo);
@@ -1729,7 +1775,7 @@ bool AnimationKeyEditor::_edit_if_single_selection() {
key_edit->animation=animation;
key_edit->track=idx;
key_edit->key_ofs=animation->track_get_key_time(idx,key);
- key_edit->hint=_find_hint_for_track(idx);
+ key_edit->hint=_find_hint_for_track(idx,key_edit->base);
key_edit->notify_change();
curve_edit->set_transition(animation->track_get_key_transition(idx,key));
@@ -2187,7 +2233,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) {
newval=d;
} else if (tt==Animation::TYPE_VALUE) {
- PropertyInfo inf = _find_hint_for_track(idx);
+ NodePath np;
+ PropertyInfo inf = _find_hint_for_track(idx,np);
if (inf.type!=Variant::NIL) {
Variant::CallError err;
@@ -2810,6 +2857,7 @@ void AnimationKeyEditor::_notification(int p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
EditorNode::get_singleton()->update_keying();
+ emit_signal("keying_changed");
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -2975,6 +3023,7 @@ void AnimationKeyEditor::_clear_selection() {
key_edit->track=0;
key_edit->key_ofs=0;
key_edit->hint=PropertyInfo();
+ key_edit->base=NodePath();
key_edit->notify_change();
}
@@ -3022,9 +3071,14 @@ Node *AnimationKeyEditor::get_root() const {
-void AnimationKeyEditor::set_keying(bool p_enabled) {
+void AnimationKeyEditor::update_keying() {
- keying=p_enabled;
+ bool keying_enabled=is_visible() && animation.is_valid();
+
+ if (keying_enabled==keying)
+ return;
+
+ keying=keying_enabled;
_update_menu();
emit_signal("keying_changed");
@@ -3032,7 +3086,7 @@ void AnimationKeyEditor::set_keying(bool p_enabled) {
bool AnimationKeyEditor::has_keying() const {
- return is_visible() && animation.is_valid();
+ return keying;
}
void AnimationKeyEditor::_query_insert(const InsertData& p_id) {
@@ -3264,9 +3318,10 @@ int AnimationKeyEditor::_confirm_insert(InsertData p_id,int p_last_track) {
{
//shitty hack
+ NodePath np;
animation->add_track(p_id.type);
animation->track_set_path(animation->get_track_count()-1,p_id.path);
- PropertyInfo h = _find_hint_for_track(animation->get_track_count()-1);
+ PropertyInfo h = _find_hint_for_track(animation->get_track_count()-1,np);
animation->remove_track(animation->get_track_count()-1); //hack
@@ -3640,6 +3695,9 @@ void AnimationKeyEditor::_add_call_track(const NodePath& p_base) {
NodePath path = root->get_path_to(from);
+ //print_line("root: "+String(root->get_path()));
+ //print_line("path: "+String(path));
+
undo_redo->create_action("Anim Add Call Track");
undo_redo->add_do_method(animation.ptr(),"add_track",Animation::TYPE_METHOD);
undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),path);
diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h
index c8a539179e..cd22dc3106 100644
--- a/tools/editor/animation_editor.h
+++ b/tools/editor/animation_editor.h
@@ -302,7 +302,7 @@ class AnimationKeyEditor : public VBoxContainer {
void _select_at_anim(const Ref<Animation>& p_anim,int p_track,float p_pos);
void _curve_transition_changed(float p_what);
- PropertyInfo _find_hint_for_track(int p_idx);
+ PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path);
void _create_value_item(int p_type);
void _pane_drag(const Point2& p_delta);
@@ -324,7 +324,7 @@ public:
Ref<Animation> get_current_animation() const;
void set_root(Node *p_root);
Node *get_root() const;
- void set_keying(bool p_enabled);
+ void update_keying();
bool has_keying() const;
void cleanup();
diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp
index c7c1a48e34..ad59efc46f 100644
--- a/tools/editor/editor_file_system.cpp
+++ b/tools/editor/editor_file_system.cpp
@@ -1166,8 +1166,10 @@ EditorFileSystemDirectory *EditorFileSystem::get_path(const String& p_path) {
void EditorFileSystem::_resource_saved(const String& p_path){
+
//print_line("resource saved: "+p_path);
EditorFileSystem::get_singleton()->update_file(p_path);
+
}
String EditorFileSystem::_find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const {
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index 2ece518f8d..ddcb634151 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -1201,7 +1201,7 @@ void EditorHelp::_add_text(const String& p_bbcode) {
class_desc->push_font(get_font("italic","Fonts"));
pos=brk_end+1;
tag_stack.push_front(tag);
- } else if (tag=="code") {
+ } else if (tag=="code" || tag=="codeblock") {
//use monospace font
class_desc->push_font(get_font("source","EditorFonts"));
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
index 77331256f3..b845eba66b 100644
--- a/tools/editor/editor_import_export.cpp
+++ b/tools/editor/editor_import_export.cpp
@@ -162,6 +162,7 @@ EditorExportPlugin::EditorExportPlugin() {
/////////////////////////////////////////////////////////////////////////////////////////////////////
+
static void _add_to_list(EditorFileSystemDirectory *p_efsd,Set<StringName>& r_list) {
for(int i=0;i<p_efsd->get_subdir_count();i++) {
@@ -170,13 +171,11 @@ static void _add_to_list(EditorFileSystemDirectory *p_efsd,Set<StringName>& r_li
}
for(int i=0;i<p_efsd->get_file_count();i++) {
-
r_list.insert(p_efsd->get_file_path(i));
}
}
-
struct __EESortDepCmp {
_FORCE_INLINE_ bool operator()(const StringName& p_l,const StringName& p_r) const {
@@ -187,7 +186,7 @@ struct __EESortDepCmp {
-static void _add_files_with_filter(DirAccess *da,const List<String>& p_filters,Set<StringName>& r_list) {
+static void _edit_files_with_filter(DirAccess *da,const List<String>& p_filters,Set<StringName>& r_list,bool exclude) {
List<String> files;
@@ -218,8 +217,17 @@ static void _add_files_with_filter(DirAccess *da,const List<String>& p_filters,S
for(const List<String>::Element *F=p_filters.front();F;F=F->next()) {
if (fullpath.matchn(F->get())) {
- r_list.insert(fullpath);
- print_line("Added: "+fullpath);
+ String act = "Added: ";
+
+ if (!exclude) {
+ r_list.insert(fullpath);
+ } else {
+ act = "Removed: ";
+ r_list.erase(fullpath);
+ }
+
+
+ print_line(act+fullpath);
}
}
}
@@ -230,13 +238,13 @@ static void _add_files_with_filter(DirAccess *da,const List<String>& p_filters,S
if (E->get().begins_with("."))
continue;
da->change_dir(E->get());
- _add_files_with_filter(da,p_filters,r_list);
+ _edit_files_with_filter(da,p_filters,r_list,exclude);
da->change_dir("..");
}
}
-static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) {
+static void _edit_filter_list(Set<StringName>& r_list,const String& p_filter,bool exclude) {
if (p_filter=="")
return;
@@ -250,11 +258,16 @@ static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter)
}
DirAccess *da = DirAccess::open("res://");
- _add_files_with_filter(da,filters,r_list);
+ _edit_files_with_filter(da,filters,r_list,exclude);
memdelete(da);
+}
+static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) {
+ _edit_filter_list(r_list,p_filter,false);
+}
-
+static void _remove_filter_from_list(Set<StringName>& r_list,const String& p_filter) {
+ _edit_filter_list(r_list,p_filter,true);
}
Vector<uint8_t> EditorExportPlatform::get_exported_file_default(String& p_fname) const {
@@ -307,6 +320,8 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const
cf+="*.flags";
_add_filter_to_list(exported,cf);
+ cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude();
+ _remove_filter_from_list(exported,cf);
}
@@ -380,6 +395,9 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const
cf+="*.flags";
_add_filter_to_list(exported,cf);
+ cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude();
+ _remove_filter_from_list(exported,cf);
+
}
@@ -1530,13 +1548,17 @@ EditorImportExport::ExportFilter EditorImportExport::get_export_filter() const{
}
void EditorImportExport::set_export_custom_filter(const String& p_custom_filter){
-
export_custom_filter=p_custom_filter;
}
+void EditorImportExport::set_export_custom_filter_exclude(const String& p_custom_filter){
+ export_custom_filter_exclude=p_custom_filter;
+}
String EditorImportExport::get_export_custom_filter() const{
-
return export_custom_filter;
}
+String EditorImportExport::get_export_custom_filter_exclude() const{
+ return export_custom_filter_exclude;
+}
void EditorImportExport::set_export_image_action(ImageAction p_action) {
@@ -1699,6 +1721,7 @@ void EditorImportExport::load_config() {
export_custom_filter=cf->get_value("export_filter","filter");
+ export_custom_filter_exclude=cf->get_value("export_filter","filter_exclude");
String t=cf->get_value("export_filter","type");
if (t=="selected")
export_filter=EXPORT_SELECTED;
@@ -1888,6 +1911,7 @@ void EditorImportExport::save_config() {
}
cf->set_value("export_filter","filter",export_custom_filter);
+ cf->set_value("export_filter", "filter_exclude",export_custom_filter_exclude);
String file_action_section = "export_filter_files";
diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h
index 272464d9b0..60b7f919d8 100644
--- a/tools/editor/editor_import_export.h
+++ b/tools/editor/editor_import_export.h
@@ -285,7 +285,7 @@ protected:
Set<String> image_formats;
ExportFilter export_filter;
- String export_custom_filter;
+ String export_custom_filter, export_custom_filter_exclude;
Map<StringName,FileAction> files;
Map<StringName,Ref<EditorExportPlatform> > exporters;
Map<StringName,ImageGroup> image_groups;
@@ -332,7 +332,9 @@ public:
ExportFilter get_export_filter() const;
void set_export_custom_filter(const String& p_custom_filter);
+ void set_export_custom_filter_exclude(const String& p_custom_filter);
String get_export_custom_filter() const;
+ String get_export_custom_filter_exclude() const;
void set_export_image_action(ImageAction p_action);
ImageAction get_export_image_action() const;
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 79f5e66401..7fa85c4476 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -328,12 +328,14 @@ void EditorNode::_notification(int p_what) {
}
*/
+ /* // moved to "_sources_changed"
if (export_defer.platform!="") {
project_export_settings->export_platform(export_defer.platform,export_defer.path,export_defer.debug,export_defer.password,true);
export_defer.platform="";
}
+ */
}
if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) {
@@ -378,6 +380,10 @@ void EditorNode::_notification(int p_what) {
_menu_option_confirm(FILE_QUIT, false);
};
+ if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
+ scene_tabs->set_tab_close_display_policy( (bool(EDITOR_DEF("global/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY) );
+ }
+
}
void EditorNode::_fs_changed() {
@@ -391,6 +397,13 @@ void EditorNode::_fs_changed() {
E->get()->invalidate();
}
+
+ if (export_defer.platform!="") {
+
+ project_export_settings->export_platform(export_defer.platform,export_defer.path,export_defer.debug,export_defer.password,true);
+ export_defer.platform="";
+ }
+
}
void EditorNode::_sources_changed(bool p_exist) {
@@ -406,6 +419,7 @@ void EditorNode::_sources_changed(bool p_exist) {
sources_button->set_disabled(true);
}
+
}
void EditorNode::_vp_resized() {
@@ -1785,6 +1799,8 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
//pause_button->set_pressed(false);
play_scene_button->set_pressed(false);
play_scene_button->set_icon(gui_base->get_icon("PlayScene","EditorIcons"));
+ play_custom_scene_button->set_pressed(false);
+ play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
String current_filename;
String run_filename;
@@ -1794,7 +1810,6 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
if (p_current || (editor_data.get_edited_scene_root() && p_custom==editor_data.get_edited_scene_root()->get_filename())) {
-
Node *scene = editor_data.get_edited_scene_root();
if (!scene) {
@@ -1903,6 +1918,10 @@ void EditorNode::_run(bool p_current,const String& p_custom) {
if (p_current) {
play_scene_button->set_pressed(true);
play_scene_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
+ } else if (p_custom!="") {
+ run_custom_filename=run_filename;
+ play_custom_scene_button->set_pressed(true);
+ play_custom_scene_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
} else {
play_button->set_pressed(true);
play_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
@@ -2214,7 +2233,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
case FILE_EXPORT_PROJECT: {
- project_export_settings->popup_centered_ratio();
+ project_export_settings->popup_export();
/*
String target = export_db->get_current_platform();
Ref<EditorExporter> exporter = export_db->get_exporter(target);
@@ -2585,9 +2604,16 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case RUN_PLAY_CUSTOM_SCENE: {
- _menu_option_confirm(RUN_STOP,true);
- quick_run->popup("PackedScene",true);
- quick_run->set_title("Quick Run Scene..");
+ if (run_custom_filename.empty() || editor_run.get_status()==EditorRun::STATUS_STOP) {
+ _menu_option_confirm(RUN_STOP,true);
+ quick_run->popup("PackedScene",true);
+ quick_run->set_title("Quick Run Scene..");
+ play_custom_scene_button->set_pressed(false);
+ } else {
+ String last_custom_scene=run_custom_filename;
+ _menu_option_confirm(RUN_STOP,true);
+ _run(false,last_custom_scene);
+ }
} break;
case RUN_PAUSE: {
@@ -2601,10 +2627,13 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
break;
editor_run.stop();
+ run_custom_filename.clear();
play_button->set_pressed(false);
play_button->set_icon(gui_base->get_icon("MainPlay","EditorIcons"));
play_scene_button->set_pressed(false);
play_scene_button->set_icon(gui_base->get_icon("PlayScene","EditorIcons"));
+ play_custom_scene_button->set_pressed(false);
+ play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
//pause_button->set_pressed(false);
emit_signal("stop_pressed");
@@ -3661,6 +3690,7 @@ void EditorNode::update_keying() {
property_editor->set_keying(valid);
+ AnimationPlayerEditor::singleton->get_key_editor()->update_keying();
}
@@ -3832,9 +3862,9 @@ void EditorNode::_quick_opened() {
}
}
-void EditorNode::_quick_run(const String& p_resource) {
+void EditorNode::_quick_run() {
- _run(false,p_resource);
+ _run(false,quick_run->get_selected());
}
@@ -5033,17 +5063,21 @@ EditorNode::EditorNode() {
scene_tabs=memnew( Tabs );
scene_tabs->add_tab("unsaved");
scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
- scene_tabs->set_tab_close_display_policy(Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY);
+ scene_tabs->set_tab_close_display_policy( (bool(EDITOR_DEF("global/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY) );
scene_tabs->connect("tab_changed",this,"_scene_tab_changed");
scene_tabs->connect("right_button_pressed",this,"_scene_tab_script_edited");
scene_tabs->connect("tab_close", this, "_scene_tab_closed");
srt->add_child(scene_tabs);
- scene_root_parent = memnew( Panel );
+ scene_root_parent = memnew( PanelContainer );
+ scene_root_parent->set_custom_minimum_size(Size2(0,80));
+
+
+ //Ref<StyleBox> sp = scene_root_parent->get_stylebox("panel","TabContainer");
+ //scene_root_parent->add_style_override("panel",sp);
+
- Ref<StyleBox> sp = scene_root_parent->get_stylebox("panel","TabContainer");
- scene_root_parent->add_style_override("panel",sp);
/*scene_root_parent->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
scene_root_parent->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END );
scene_root_parent->set_begin( Point2( 0, 0) );
@@ -5051,13 +5085,6 @@ EditorNode::EditorNode() {
srt->add_child(scene_root_parent);
scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- scene_root_base = memnew( Control );
- scene_root_base->set_area_as_parent_rect();
- for(int i=0;i<4;i++) {
- scene_root_base->set_margin(Margin(i),sp->get_margin(Margin(i)));
- }
- scene_root_parent->add_child(scene_root_base);
-
scene_root = memnew( Viewport );
@@ -5072,11 +5099,11 @@ EditorNode::EditorNode() {
// scene_root->set_world_2d( Ref<World2D>( memnew( World2D )) );
- viewport = memnew( Control );
- viewport->set_area_as_parent_rect(4);
- for(int i=0;i<4;i++) {
+ viewport = memnew( VBoxContainer );
+ viewport->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ /*for(int i=0;i<4;i++) {
viewport->set_margin(Margin(i),sp->get_margin(Margin(i)));
- }
+ }*/
scene_root_parent->add_child(viewport);
@@ -5858,7 +5885,8 @@ EditorNode::EditorNode() {
// Ref<EditorSceneImporterFBXConv> _fbxconv_import = memnew( EditorSceneImporterFBXConv);
// _scene_import->add_importer(_fbxconv_import);
editor_import_export->add_import_plugin( _scene_import);
- editor_import_export->add_import_plugin( Ref<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this))));
+ // TODO: This plugin has no code, it should be either implemented or dropped (GH-3667)
+ // editor_import_export->add_import_plugin( Ref<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this))));
editor_import_export->add_import_plugin( Ref<EditorMeshImportPlugin>( memnew(EditorMeshImportPlugin(this))));
editor_import_export->add_import_plugin( Ref<EditorFontImportPlugin>( memnew(EditorFontImportPlugin(this))));
editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this))));
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index c687643d30..a83555d6e8 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -258,7 +258,7 @@ class EditorNode : public Node {
TextEdit *load_errors;
AcceptDialog *load_error_dialog;
- Control *scene_root_base;
+ //Control *scene_root_base;
Ref<Theme> theme;
PopupMenu *recent_scenes;
@@ -355,6 +355,7 @@ class EditorNode : public Node {
Object *current;
bool _playing_edited;
+ String run_custom_filename;
bool reference_resource_mem;
bool save_external_resources_mem;
uint64_t saved_version;
@@ -447,7 +448,7 @@ class EditorNode : public Node {
void _hide_top_editors();
void _quick_opened();
- void _quick_run(const String& p_resource);
+ void _quick_run();
void _run(bool p_current=false, const String &p_custom="");
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 4195ba97e6..78fde9950d 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -165,22 +165,33 @@ void EditorSettings::create() {
return; //pointless
DirAccess *dir=NULL;
- Object *object;
Variant meta;
String config_path;
String config_dir;
String config_file="editor_settings.xml";
+ Ref<ConfigFile> extra_config = memnew(ConfigFile);
- if (OS::get_singleton()->has_environment("APPDATA")) {
- // Most likely under windows, save here
- config_path=OS::get_singleton()->get_environment("APPDATA");
- config_dir=String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
- } else if (OS::get_singleton()->has_environment("HOME")) {
+ String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
+ DirAccess* d = DirAccess::create_for_path(exe_path);
+ if (d->file_exists(exe_path + "/._sc_")) {
- config_path=OS::get_singleton()->get_environment("HOME");
- config_dir="."+String(_MKSTR(VERSION_SHORT_NAME)).to_lower();
- }
+ // editor is self contained
+ config_path = exe_path;
+ config_dir = "editor_data";
+ extra_config->load(exe_path + "/._sc_");
+ } else {
+
+ if (OS::get_singleton()->has_environment("APPDATA")) {
+ // Most likely under windows, save here
+ config_path=OS::get_singleton()->get_environment("APPDATA");
+ config_dir=String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
+ } else if (OS::get_singleton()->has_environment("HOME")) {
+
+ config_path=OS::get_singleton()->get_environment("HOME");
+ config_dir="."+String(_MKSTR(VERSION_SHORT_NAME)).to_lower();
+ }
+ };
ObjectTypeDB::register_type<EditorSettings>(); //otherwise it can't be unserialized
String config_file_path;
@@ -286,10 +297,20 @@ void EditorSettings::create() {
fail:
+ // patch init projects
+ if (extra_config->has_section("init_projects")) {
+ Vector<String> list = extra_config->get_value("init_projects", "list");
+ for (int i=0; i<list.size(); i++) {
+
+ list[i] = exe_path + "/" + list[i];
+ };
+ extra_config->set_value("init_projects", "list", list);
+ };
+
singleton = Ref<EditorSettings>( memnew( EditorSettings ) );
singleton->config_file_path=config_file_path;
singleton->settings_path=config_path+"/"+config_dir;
- singleton->_load_defaults();
+ singleton->_load_defaults(extra_config);
singleton->setup_network();
singleton->scan_plugins();
@@ -435,7 +456,7 @@ void EditorSettings::destroy() {
singleton=Ref<EditorSettings>();
}
-void EditorSettings::_load_defaults() {
+void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_THREAD_SAFE_METHOD_
@@ -490,6 +511,7 @@ void EditorSettings::_load_defaults() {
hints["3d_editor/pan_modifier"]=PropertyInfo(Variant::INT,"3d_editor/pan_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
set("3d_editor/zoom_modifier",4);
hints["3d_editor/zoom_modifier"]=PropertyInfo(Variant::INT,"3d_editor/zoom_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
+ set("3d_editor/emulate_numpad",false);
set("2d_editor/bone_width",5);
set("2d_editor/bone_color1",Color(1.0,1.0,1.0,0.9));
@@ -541,6 +563,17 @@ void EditorSettings::_load_defaults() {
set("run/auto_save_before_running",true);
set("resources/save_compressed_resources",true);
set("resources/auto_reload_modified_images",true);
+
+ if (p_extra_config.is_valid() && p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) {
+
+ Vector<String> list = p_extra_config->get_value("init_projects", "list");
+ for (int i=0; i<list.size(); i++) {
+
+ String name = list[i].replace("/", "::");
+ set("projects/"+name, list[i]);
+ };
+ };
+
}
void EditorSettings::notify_changes() {
diff --git a/tools/editor/editor_settings.h b/tools/editor/editor_settings.h
index d1a11360af..40aa00015e 100644
--- a/tools/editor/editor_settings.h
+++ b/tools/editor/editor_settings.h
@@ -33,6 +33,7 @@
#include "resource.h"
#include "os/thread_safe.h"
+#include "core/io/config_file.h"
class EditorPlugin;
@@ -86,7 +87,7 @@ private:
EditorPlugin *_load_plugin_editor(const String& p_path);
Error _load_plugin(const String& p_path,Plugin& plugin);
- void _load_defaults();
+ void _load_defaults(Ref<ConfigFile> p_extra_config = NULL);
String project_config_path;
diff --git a/tools/editor/icons/icon_array_data.png b/tools/editor/icons/icon_array_data.png
index 494d4c71a8..447acaab2b 100644
--- a/tools/editor/icons/icon_array_data.png
+++ b/tools/editor/icons/icon_array_data.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_float.png b/tools/editor/icons/icon_array_float.png
index 558be932dc..d1b78b4c3e 100644
--- a/tools/editor/icons/icon_array_float.png
+++ b/tools/editor/icons/icon_array_float.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_int.png b/tools/editor/icons/icon_array_int.png
index 74925553d9..2c4ec5bafb 100644
--- a/tools/editor/icons/icon_array_int.png
+++ b/tools/editor/icons/icon_array_int.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_string.png b/tools/editor/icons/icon_array_string.png
index 2aeded63df..a2e3f11c35 100644
--- a/tools/editor/icons/icon_array_string.png
+++ b/tools/editor/icons/icon_array_string.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_variant.png b/tools/editor/icons/icon_array_variant.png
index 34cb83cadd..ab294898ad 100644
--- a/tools/editor/icons/icon_array_variant.png
+++ b/tools/editor/icons/icon_array_variant.png
Binary files differ
diff --git a/tools/editor/icons/icon_bool.png b/tools/editor/icons/icon_bool.png
index 3381033b00..80b3a9deb7 100644
--- a/tools/editor/icons/icon_bool.png
+++ b/tools/editor/icons/icon_bool.png
Binary files differ
diff --git a/tools/editor/icons/icon_color.png b/tools/editor/icons/icon_color.png
index 08547caa28..3ab87c98ea 100644
--- a/tools/editor/icons/icon_color.png
+++ b/tools/editor/icons/icon_color.png
Binary files differ
diff --git a/tools/editor/icons/icon_integer.png b/tools/editor/icons/icon_integer.png
index 32c8d9885b..b49390aeb1 100644
--- a/tools/editor/icons/icon_integer.png
+++ b/tools/editor/icons/icon_integer.png
Binary files differ
diff --git a/tools/editor/icons/icon_quat.png b/tools/editor/icons/icon_quat.png
index ebb8719d33..f09d2fcaba 100644
--- a/tools/editor/icons/icon_quat.png
+++ b/tools/editor/icons/icon_quat.png
Binary files differ
diff --git a/tools/editor/icons/icon_real.png b/tools/editor/icons/icon_real.png
index 80fbf7017c..7f5bf08ede 100644
--- a/tools/editor/icons/icon_real.png
+++ b/tools/editor/icons/icon_real.png
Binary files differ
diff --git a/tools/editor/icons/icon_rect2.png b/tools/editor/icons/icon_rect2.png
index e9293b5fad..cf3cfe3b22 100644
--- a/tools/editor/icons/icon_rect2.png
+++ b/tools/editor/icons/icon_rect2.png
Binary files differ
diff --git a/tools/editor/icons/icon_rect3.png b/tools/editor/icons/icon_rect3.png
index e1e81f84e7..8eacfff207 100644
--- a/tools/editor/icons/icon_rect3.png
+++ b/tools/editor/icons/icon_rect3.png
Binary files differ
diff --git a/tools/editor/icons/icon_reload_empty.png b/tools/editor/icons/icon_reload_empty.png
new file mode 100644
index 0000000000..d43582b2c4
--- /dev/null
+++ b/tools/editor/icons/icon_reload_empty.png
Binary files differ
diff --git a/tools/editor/icons/icon_reload_small.png b/tools/editor/icons/icon_reload_small.png
new file mode 100644
index 0000000000..957cdfcf4f
--- /dev/null
+++ b/tools/editor/icons/icon_reload_small.png
Binary files differ
diff --git a/tools/editor/icons/icon_string.png b/tools/editor/icons/icon_string.png
index 48bf753c40..4a747f7c62 100644
--- a/tools/editor/icons/icon_string.png
+++ b/tools/editor/icons/icon_string.png
Binary files differ
diff --git a/tools/editor/icons/icon_vector.png b/tools/editor/icons/icon_vector.png
index 0ee33ba0b7..0bda8ff7c0 100644
--- a/tools/editor/icons/icon_vector.png
+++ b/tools/editor/icons/icon_vector.png
Binary files differ
diff --git a/tools/editor/icons/icon_vector2.png b/tools/editor/icons/icon_vector2.png
index 5920109a55..5bfd08f52a 100644
--- a/tools/editor/icons/icon_vector2.png
+++ b/tools/editor/icons/icon_vector2.png
Binary files differ
diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp
index b81c88c817..5408e43e1a 100644
--- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp
@@ -481,10 +481,10 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI
float mu = pos-Math::floor(pos);
int ipos = int(Math::floor(pos));
- float y0=data[MAX(0,ipos-i)];
- float y1=data[ipos];
- float y2=data[MIN(len-1,ipos+1)];
- float y3=data[MIN(len-1,ipos+2)];
+ float y0=data[MAX(0,ipos-1)*chans+c];
+ float y1=data[ipos*chans+c];
+ float y2=data[MIN(len-1,ipos+1)*chans+c];
+ float y3=data[MIN(len-1,ipos+2)*chans+c];
float mu2 = mu*mu;
float a0 = y3 - y2 - y0 + y1;
diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp
index 43b4276d45..010753e88c 100644
--- a/tools/editor/plugins/animation_player_editor_plugin.cpp
+++ b/tools/editor/plugins/animation_player_editor_plugin.cpp
@@ -128,16 +128,9 @@ void AnimationPlayerEditor::_notification(int p_what) {
anim_editor_load->set_hover_texture( get_icon("AnimGetHl","EditorIcons"));
anim_editor_store->set_hover_texture( get_icon("AnimSetHl","EditorIcons"));
*/
- }
-
- if (p_what==NOTIFICATION_READY) {
get_tree()->connect("node_removed",this,"_node_removed");
}
-
- if (p_what==NOTIFICATION_DRAW) {
-
- }
}
void AnimationPlayerEditor::_autoplay_pressed() {
@@ -628,10 +621,11 @@ void AnimationPlayerEditor::ensure_visibility() {
Dictionary AnimationPlayerEditor::get_state() const {
+
Dictionary d;
d["visible"]=is_visible();
- if (is_visible() && player) {
+ if (EditorNode::get_singleton()->get_edited_scene() && is_visible() && player) {
d["player"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(player);
d["animation"]=player->get_current_animation();
@@ -644,6 +638,9 @@ void AnimationPlayerEditor::set_state(const Dictionary& p_state) {
if (p_state.has("visible") && p_state["visible"]) {
+ if (!EditorNode::get_singleton()->get_edited_scene())
+ return;
+
Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]);
if (n && n->cast_to<AnimationPlayer>()) {
player=n->cast_to<AnimationPlayer>();
@@ -949,6 +946,14 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value) {
anim=player->get_animation(current);
float pos = anim->get_length() * (p_value / frame->get_max());
+ float step = anim->get_step();
+ if (step) {
+ pos=Math::stepify(pos, step);
+ if (pos<0)
+ pos=0;
+ if (pos>=anim->get_length())
+ pos=anim->get_length();
+ }
if (player->is_valid()) {
float cpos = player->get_current_animation_pos();
@@ -1305,7 +1310,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
frame = memnew( SpinBox );
hb->add_child(frame);
- frame->set_custom_minimum_size(Size2(80,0));
+ frame->set_custom_minimum_size(Size2(60,0));
frame->set_stretch_ratio(2);
frame->set_tooltip("Animation position (in seconds).");
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index 0afea26957..f8bc97a433 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -409,7 +409,7 @@ void CanvasItemEditor::_node_removed(Node *p_node) {
void CanvasItemEditor::_keying_changed() {
- if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying())
+ if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible())
animation_hb->show();
else
animation_hb->hide();
@@ -1560,7 +1560,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
Matrix32 rot;
rot.elements[1] = (dfrom - center).normalized();
rot.elements[0] = rot.elements[1].tangent();
- node->set_rot(snap_angle(rot.xform_inv(dto-center).angle(), node->get_rot()));
+ node->set_rot(snap_angle(rot.xform_inv(dto-center).angle() + node->get_rot(), node->get_rot()));
display_rotate_to = dto;
display_rotate_from = center;
viewport->update();
@@ -2233,6 +2233,8 @@ void CanvasItemEditor::_notification(int p_what) {
p->add_icon_item(get_icon("ControlAlignWide","EditorIcons"),"Full Rect",ANCHOR_ALIGN_WIDE);
+ AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed",this,"_keying_changed");
+ _keying_changed();
}
if (p_what==NOTIFICATION_READY) {
@@ -3477,7 +3479,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
box_selecting=false;
//zoom=0.5;
singleton=this;
- AnimationPlayerEditor::singleton->get_key_editor()->connect("keying_changed",this,"_keying_changed");
+
set_process_unhandled_key_input(true);
can_move_pivot=false;
drag=DRAG_NONE;
@@ -3528,6 +3530,7 @@ CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) {
editor=p_node;
canvas_item_editor = memnew( CanvasItemEditor(editor) );
+ canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->get_viewport()->add_child(canvas_item_editor);
canvas_item_editor->set_area_as_parent_rect();
canvas_item_editor->hide();
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 34d7e89760..8d0527cff7 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -609,7 +609,7 @@ void ScriptEditor::_breaked(bool p_breaked,bool p_can_debug) {
void ScriptEditor::_show_debugger(bool p_show) {
- debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW), p_show);
+// debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW), p_show);
}
void ScriptEditor::_script_created(Ref<Script> p_script) {
@@ -935,6 +935,9 @@ void ScriptEditor::_menu_option(int p_option) {
if (!_test_script_times_on_disk())
return;
+ save_all_scripts();
+
+#if 0
for(int i=0;i<tab_container->get_child_count();i++) {
ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
@@ -951,7 +954,7 @@ void ScriptEditor::_menu_option(int p_option) {
editor->save_resource( script );
}
-
+#endif
} break;
case SEARCH_HELP: {
@@ -976,7 +979,7 @@ void ScriptEditor::_menu_option(int p_option) {
} break;
case SEARCH_WEBSITE: {
- OS::get_singleton()->shell_open("http://www.godotengine.org/projects/godot-engine/wiki/Documentation#Tutorials");
+ OS::get_singleton()->shell_open("http://docs.godotengine.org/");
} break;
case WINDOW_NEXT: {
@@ -1694,7 +1697,7 @@ void ScriptEditor::ensure_select_current() {
Ref<Script> script = ste->get_edited_script();
- if (!grab_focus_block && is_inside_tree())
+ if (!grab_focus_block && is_visible())
ste->get_text_edit()->grab_focus();
edit_menu->show();
@@ -1938,9 +1941,7 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
}
}
-void ScriptEditor::save_external_data() {
-
- apply_scripts();
+void ScriptEditor::save_all_scripts() {
for(int i=0;i<tab_container->get_child_count();i++) {
@@ -1949,9 +1950,13 @@ void ScriptEditor::save_external_data() {
if (!ste)
continue;
+ if (ste->get_text_edit()->get_version()==ste->get_text_edit()->get_saved_version())
+ continue;
+
Ref<Script> script = ste->get_edited_script();
if (script->get_path()!="" && script->get_path().find("local://")==-1 &&script->get_path().find("::")==-1) {
//external script, save it
+ ste->apply_code();
editor->save_resource(script);
//ResourceSaver::save(script->get_path(),script);
}
@@ -2063,7 +2068,7 @@ void ScriptEditor::_editor_settings_changed() {
void ScriptEditor::_autosave_scripts() {
print_line("autosaving");
- save_external_data();
+ save_all_scripts();
}
void ScriptEditor::_tree_changed() {
@@ -2481,13 +2486,13 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
script_back->connect("pressed",this,"_history_back");
menu_hb->add_child(script_back);
script_back->set_disabled(true);
- help_search->set_tooltip("Go to previous edited document.");
+ script_back->set_tooltip("Go to previous edited document.");
script_forward = memnew( ToolButton );
script_forward->connect("pressed",this,"_history_forward");
menu_hb->add_child(script_forward);
script_forward->set_disabled(true);
- help_search->set_tooltip("Go to next edited document.");
+ script_forward->set_tooltip("Go to next edited document.");
@@ -2628,7 +2633,7 @@ void ScriptEditorPlugin::clear() {
void ScriptEditorPlugin::save_external_data() {
- script_editor->save_external_data();
+ script_editor->save_all_scripts();
}
void ScriptEditorPlugin::apply_changes() {
@@ -2672,7 +2677,7 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
editor=p_node;
script_editor = memnew( ScriptEditor(p_node) );
editor->get_viewport()->add_child(script_editor);
- script_editor->set_area_as_parent_rect();
+ script_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
script_editor->hide();
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
index c52da41a43..5664b26580 100644
--- a/tools/editor/plugins/script_editor_plugin.h
+++ b/tools/editor/plugins/script_editor_plugin.h
@@ -295,7 +295,7 @@ public:
void swap_lines(TextEdit *tx, int line1, int line2);
- void save_external_data();
+ void save_all_scripts();
void set_window_layout(Ref<ConfigFile> p_layout);
void get_window_layout(Ref<ConfigFile> p_layout);
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
index 236d69dfb3..bc57fd7e44 100644
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ b/tools/editor/plugins/spatial_editor_plugin.cpp
@@ -1631,8 +1631,11 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
_edit.snap=true;
}
} break;
+ case KEY_7:
case KEY_KP_7: {
-
+ bool emulate_numpad = EditorSettings::get_singleton()->get("3d_editor/emulate_numpad");
+ if (!emulate_numpad && k.scancode==KEY_7)
+ return;
cursor.y_rot=0;
if (k.mod.shift) {
cursor.x_rot=-Math_PI/2.0;
@@ -1647,8 +1650,11 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
_update_name();
}
} break;
+ case KEY_1:
case KEY_KP_1: {
-
+ bool emulate_numpad = EditorSettings::get_singleton()->get("3d_editor/emulate_numpad");
+ if (!emulate_numpad && k.scancode==KEY_1)
+ return;
cursor.x_rot=0;
if (k.mod.shift) {
cursor.y_rot=Math_PI;
@@ -1664,8 +1670,11 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
}
} break;
+ case KEY_3:
case KEY_KP_3: {
-
+ bool emulate_numpad = EditorSettings::get_singleton()->get("3d_editor/emulate_numpad");
+ if (!emulate_numpad && k.scancode==KEY_3)
+ return;
cursor.x_rot=0;
if (k.mod.shift) {
cursor.y_rot=Math_PI/2.0;
@@ -1680,8 +1689,11 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
}
} break;
+ case KEY_5:
case KEY_KP_5: {
-
+ bool emulate_numpad = EditorSettings::get_singleton()->get("3d_editor/emulate_numpad");
+ if (!emulate_numpad && k.scancode==KEY_5)
+ return;
//orthogonal = !orthogonal;
_menu_option(orthogonal?VIEW_PERSPECTIVE:VIEW_ORTHOGONAL);
@@ -4217,8 +4229,10 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) {
editor=p_node;
spatial_editor = memnew( SpatialEditor(p_node) );
+ spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->get_viewport()->add_child(spatial_editor);
- spatial_editor->set_area_as_parent_rect();
+
+ //spatial_editor->set_area_as_parent_rect();
spatial_editor->hide();
spatial_editor->connect("transform_key_request",editor,"_transform_keyed");
diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp
index 7690d31e7b..b5e7715d93 100644
--- a/tools/editor/project_export.cpp
+++ b/tools/editor/project_export.cpp
@@ -122,6 +122,15 @@ void ProjectExportDialog::_tree_changed() {
}
+void ProjectExportDialog::popup_export() {
+ popup_centered_ratio();
+ if (pending_update_tree) {
+ _update_tree();
+ _update_group_tree();
+ pending_update_tree=false;
+ }
+}
+
void ProjectExportDialog::_update_tree() {
@@ -168,6 +177,11 @@ void ProjectExportDialog::_scan_finished() {
print_line("**********SCAN DONEEE********");
print_line("**********SCAN DONEEE********");*/
+ if (!is_visible()) {
+ pending_update_tree=true;
+ return;
+ }
+
_update_tree();
_update_group_tree();
}
@@ -203,6 +217,11 @@ void ProjectExportDialog::_filters_edited(String what) {
_save_export_cfg();
}
+void ProjectExportDialog::_filters_exclude_edited(String what) {
+ EditorImportExport::get_singleton()->set_export_custom_filter_exclude(what);
+ _save_export_cfg();
+}
+
void ProjectExportDialog::_quality_edited(float what) {
EditorImportExport::get_singleton()->set_export_image_quality(what);
@@ -300,6 +319,7 @@ void ProjectExportDialog::_notification(int p_what) {
export_mode->select( EditorImportExport::get_singleton()->get_export_filter() );
convert_text_scenes->set_pressed( EditorImportExport::get_singleton()->get_convert_text_scenes() );
filters->set_text( EditorImportExport::get_singleton()->get_export_custom_filter() );
+ filters_exclude->set_text( EditorImportExport::get_singleton()->get_export_custom_filter_exclude() );
if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED)
tree_vb->hide();
else
@@ -1069,6 +1089,7 @@ void ProjectExportDialog::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_prop_edited"),&ProjectExportDialog::_prop_edited);
ObjectTypeDB::bind_method(_MD("_export_mode_changed"),&ProjectExportDialog::_export_mode_changed);
ObjectTypeDB::bind_method(_MD("_filters_edited"),&ProjectExportDialog::_filters_edited);
+ ObjectTypeDB::bind_method(_MD("_filters_exclude_edited"),&ProjectExportDialog::_filters_exclude_edited);
ObjectTypeDB::bind_method(_MD("_export_action"),&ProjectExportDialog::_export_action);
ObjectTypeDB::bind_method(_MD("_export_action_pck"),&ProjectExportDialog::_export_action_pck);
ObjectTypeDB::bind_method(_MD("_quality_edited"),&ProjectExportDialog::_quality_edited);
@@ -1181,8 +1202,11 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
tree->set_column_min_width(1,90);
filters = memnew( LineEdit );
- vb->add_margin_child("Filters to export non-resource files (Comma Separated, ie: *.json, *.txt):",filters);
+ vb->add_margin_child("Filters to export non-resource files (Comma Separated, eg: *.json, *.txt):",filters);
filters->connect("text_changed",this,"_filters_edited");
+ filters_exclude = memnew( LineEdit );
+ vb->add_margin_child("Filters to exclude from export (Comma Separated, eg: *.json, *.txt):",filters_exclude);
+ filters_exclude->connect("text_changed",this,"_filters_exclude_edited");
convert_text_scenes = memnew( CheckButton );
convert_text_scenes->set_text("Convert text scenes to binary on export");
@@ -1446,7 +1470,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
ei="EditorIcons";
ot="Object";
-
+ pending_update_tree=true;
}
@@ -1480,6 +1504,8 @@ void ProjectExport::popup_export() {
popup_centered(Size2(300,100));
+
+
}
Error ProjectExport::export_project(const String& p_preset) {
@@ -1880,5 +1906,6 @@ ProjectExport::ProjectExport(EditorData* p_data) {
error = memnew( AcceptDialog );
add_child(error);
+
}
diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h
index 5a42a58e58..dc076ce201 100644
--- a/tools/editor/project_export.h
+++ b/tools/editor/project_export.h
@@ -70,11 +70,12 @@ private:
TabContainer *sections;
bool updating_tree;
+ bool pending_update_tree;
AcceptDialog *error;
ConfirmationDialog *confirm;
Button *button_reload;
- LineEdit *filters;
+ LineEdit *filters, *filters_exclude;
HBoxContainer *plat_errors;
Label *platform_error_string;
@@ -154,6 +155,7 @@ private:
void _platform_selected();
void _filters_edited(String what);
+ void _filters_exclude_edited(String what);
void _update_group_tree();
void _image_filter_changed(String);
@@ -203,6 +205,7 @@ public:
Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false);
+ void popup_export();
ProjectExportDialog(EditorNode *p_editor);
~ProjectExportDialog();
};
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index 589d9d3d99..579eb8c7c7 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -788,7 +788,7 @@ void ProjectManager::_erase_project() {
return;
- erase_ask->set_text("Erase project from list?? (Folder contents will not be modified)");
+ erase_ask->set_text("Remove project from list?? (Folder contents will not be modified)");
erase_ask->popup_centered_minsize();
}
@@ -943,7 +943,7 @@ ProjectManager::ProjectManager() {
Button* erase = memnew( Button );
- erase->set_text("Erase");
+ erase->set_text("Remove");
tree_vb->add_child(erase);
erase->connect("pressed", this,"_erase_project");
erase_btn=erase;
@@ -970,7 +970,7 @@ ProjectManager::ProjectManager() {
erase_ask = memnew( ConfirmationDialog );
- erase_ask->get_ok()->set_text("Erase");
+ erase_ask->get_ok()->set_text("Remove");
erase_ask->get_ok()->connect("pressed", this,"_erase_project_confirm");
add_child(erase_ask);
diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp
index 6c5e18ec9a..fd76ea3087 100644
--- a/tools/editor/project_settings.cpp
+++ b/tools/editor/project_settings.cpp
@@ -38,18 +38,18 @@
ProjectSettings *ProjectSettings::singleton=NULL;
static const char* _button_names[JOY_BUTTON_MAX]={
-"PS X, XBox A, NDS B",
-"PS Circle, XBox B, NDS A",
-"PS Square, XBox X, NDS Y",
-"PS Triangle, XBox Y, NDS X",
-"L, L1, Wii C",
+"PS X, XBox A, Nintendo B",
+"PS Circle, XBox B, Nintendo A",
+"PS Square, XBox X, Nintendo Y",
+"PS Triangle, XBox Y, Nintendo X",
+"L, L1",
"R, R1",
-"L2, Wii Z",
+"L2",
"R2",
"L3",
"R3",
-"Select, Wii -",
-"Start, Wii +",
+"Select, Nintendo -",
+"Start, Nintendo +",
"D-Pad Up",
"D-Pad Down",
"D-Pad Left",
@@ -97,26 +97,63 @@ void ProjectSettings::_notification(int p_what) {
}
}
-void ProjectSettings::_action_persist_toggle() {
+void ProjectSettings::_action_selected() {
+ TreeItem *ti=input_editor->get_selected();
+ if (!ti || !ti->is_editable(0))
+ return;
+
+ add_at="input/"+ti->get_text(0);
+}
+
+void ProjectSettings::_action_edited() {
TreeItem *ti=input_editor->get_selected();
if (!ti)
return;
- String name="input/"+ti->get_text(0);
+ String new_name=ti->get_text(0);
+ String old_name=add_at.substr(add_at.find("/")+1,add_at.length());
- bool prev = Globals::get_singleton()->is_persisting(name);
- print_line("prev persist: "+itos(prev));
- print_line("new persist: "+itos(ti->is_checked(0)));
- if (prev==ti->is_checked(0))
+ if (new_name==old_name)
return;
+ if (new_name.find("/")!=-1 || new_name.find(":")!=-1 || new_name=="") {
+
+ ti->set_text(0,old_name);
+ add_at="input/"+old_name;
+
+ message->set_text("Invalid Action (Anything goes but / or :).");
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ String action_prop="input/"+new_name;
+
+ if (Globals::get_singleton()->has(action_prop)) {
+
+ ti->set_text(0,old_name);
+ add_at="input/"+old_name;
+
+ message->set_text("Action '"+new_name+"' already exists!.");
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ int order = Globals::get_singleton()->get_order(add_at);
+ Array va = Globals::get_singleton()->get(add_at);
+ bool persisting = Globals::get_singleton()->is_persisting(add_at);
setting=true;
- undo_redo->create_action("Change Input Action Persistence");
- undo_redo->add_do_method(Globals::get_singleton(),"set_persisting",name,ti->is_checked(0));
- undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",name,prev);
+ undo_redo->create_action("Rename Input Action Event");
+ undo_redo->add_do_method(Globals::get_singleton(),"clear",add_at);
+ undo_redo->add_do_method(Globals::get_singleton(),"set",action_prop,va);
+ undo_redo->add_do_method(Globals::get_singleton(),"set_persisting",action_prop,persisting);
+ undo_redo->add_do_method(Globals::get_singleton(),"set_order",action_prop,order);
+ undo_redo->add_undo_method(Globals::get_singleton(),"clear",action_prop);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set",add_at,va);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",add_at,persisting);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",add_at,order);
undo_redo->add_do_method(this,"_update_actions");
undo_redo->add_undo_method(this,"_update_actions");
undo_redo->add_do_method(this,"_settings_changed");
@@ -124,6 +161,8 @@ void ProjectSettings::_action_persist_toggle() {
undo_redo->commit_action();
setting=false;
+ add_at=action_prop;
+
}
@@ -297,12 +336,24 @@ void ProjectSettings::_add_item(int p_item){
case InputEvent::JOYSTICK_MOTION: {
device_id->set_val(0);
- device_index_label->set_text("Joy Button Axis:");
+ device_index_label->set_text("Joystick Axis Index:");
device_index->clear();
- for(int i=0;i<24;i++) {
+ for(int i=0;i<JOY_AXIS_MAX*2;i++) {
+
+ String desc;
+ int ax=i/2;
+ if (ax==0 || ax==1)
+ desc=" (Left Stick)";
+ else if (ax==2 || ax==3)
+ desc=" (Right Stick)";
+ else if (ax==6)
+ desc=" (L2)";
+ else if (ax==7)
+ desc=" (R2)";
- device_index->add_item("Axis "+itos(i/2)+" "+(i&1?"+":"-"));
+
+ device_index->add_item("Axis "+itos(i/2)+" "+(i&1?"+":"-")+desc);
}
device_input->popup_centered(Size2(350,95));
@@ -310,12 +361,12 @@ void ProjectSettings::_add_item(int p_item){
case InputEvent::JOYSTICK_BUTTON: {
device_id->set_val(0);
- device_index_label->set_text("Joy Button Index:");
+ device_index_label->set_text("Joystick Button Index:");
device_index->clear();
for(int i=0;i<JOY_BUTTON_MAX;i++) {
- device_index->add_item(String(_button_names[i]));
+ device_index->add_item(itos(i)+": "+String(_button_names[i]));
}
device_input->popup_centered(Size2(350,95));
@@ -344,15 +395,6 @@ void ProjectSettings::_action_button_pressed(Object* p_obj, int p_column,int p_i
add_at="input/"+ti->get_text(0);
} else if (p_id==2) {
- //rename
-
- add_at="input/"+ti->get_text(0);
- rename_action->popup_centered();
- rename_action->get_line_edit()->set_text(ti->get_text(0));
- rename_action->get_line_edit()->set_cursor_pos(ti->get_text(0).length());
- rename_action->get_line_edit()->select_all();
-
- } else if (p_id==3) {
//remove
if (ti->get_parent()==input_editor->get_root()) {
@@ -434,15 +476,13 @@ void ProjectSettings::_update_actions() {
item->set_text(0,name);
item->add_button(0,get_icon("Add","EditorIcons"),1);
if (!Globals::get_singleton()->get_input_presets().find(pi.name)) {
- item->add_button(0,get_icon("Rename","EditorIcons"),2);
- item->add_button(0,get_icon("Remove","EditorIcons"),3);
+ item->add_button(0,get_icon("Remove","EditorIcons"),2);
+ item->set_editable(0,true);
}
item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
- item->set_editable(0,true);
//item->set_checked(0,pi.usage&PROPERTY_USAGE_CHECKED);
-
Array actions=Globals::get_singleton()->get(pi.name);
for(int i=0;i<actions.size();i++) {
@@ -474,7 +514,7 @@ void ProjectSettings::_update_actions() {
case InputEvent::JOYSTICK_BUTTON: {
String str = "Device "+itos(ie.device)+", Button "+itos(ie.joy_button.button_index);
- if (ie.joy_button.button_index>=0 && ie.joy_button.button_index<14)
+ if (ie.joy_button.button_index>=0 && ie.joy_button.button_index<JOY_BUTTON_MAX)
str+=String()+" ("+_button_names[ie.joy_button.button_index]+").";
else
str+=".";
@@ -499,12 +539,23 @@ void ProjectSettings::_update_actions() {
} break;
case InputEvent::JOYSTICK_MOTION: {
- String str = "Device "+itos(ie.device)+", Axis "+itos(ie.joy_motion.axis)+" "+(ie.joy_motion.axis_value<0?"-.":"+.");
+ String desc;
+ int ax = ie.joy_motion.axis;
+
+ if (ax==0 || ax==1)
+ desc=" (Left Stick).";
+ else if (ax==2 || ax==3)
+ desc=" (Right Stick).";
+ else if (ax==6)
+ desc=" (L2).";
+ else if (ax==7)
+ desc=" (R2).";
+ String str = "Device "+itos(ie.device)+", Axis "+itos(ie.joy_motion.axis)+" "+(ie.joy_motion.axis_value<0?"-":"+")+desc;
action->set_text(0,str);
action->set_icon(0,get_icon("JoyAxis","EditorIcons"));
} break;
}
- action->add_button(0,get_icon("Remove","EditorIcons"),3);
+ action->add_button(0,get_icon("Remove","EditorIcons"),2);
action->set_metadata(0,i);
}
}
@@ -635,45 +686,6 @@ void ProjectSettings::_action_add() {
}
-void ProjectSettings::_action_rename(const String &p_name) {
-
-
- if (p_name.find("/")!=-1 || p_name.find(":")!=-1 || p_name=="") {
- message->set_text("Invalid Action (Anything goes but / or :).");
- message->popup_centered(Size2(300,100));
- return;
- }
-
- String new_name = "input/"+p_name;
-
- if (Globals::get_singleton()->has(new_name)) {
- message->set_text("Action '"+p_name+"' already exists!.");
- message->popup_centered(Size2(300,100));
- return;
- }
-
- int order = Globals::get_singleton()->get_order(add_at);
- Array va = Globals::get_singleton()->get(add_at);
- bool persisting = Globals::get_singleton()->is_persisting(add_at);
-
- undo_redo->create_action("Rename Input Action Event");
- undo_redo->add_do_method(Globals::get_singleton(),"clear",add_at);
- undo_redo->add_do_method(Globals::get_singleton(),"set",new_name,va);
- undo_redo->add_do_method(Globals::get_singleton(),"set_persisting",new_name,persisting);
- undo_redo->add_do_method(Globals::get_singleton(),"set_order",new_name,order);
- undo_redo->add_undo_method(Globals::get_singleton(),"clear",new_name);
- undo_redo->add_undo_method(Globals::get_singleton(),"set",add_at,va);
- undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",add_at,persisting);
- undo_redo->add_undo_method(Globals::get_singleton(),"set_order",add_at,order);
- undo_redo->add_do_method(this,"_update_actions");
- undo_redo->add_undo_method(this,"_update_actions");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
-
- rename_action->hide();
-}
-
void ProjectSettings::_item_checked(const String& p_item, bool p_check) {
@@ -823,6 +835,7 @@ void ProjectSettings::_autoload_edited() {
String base="autoload/"+ti->get_text(0);
String path = Globals::get_singleton()->get(base);
+ int order = Globals::get_singleton()->get_order(base);
if (path.begins_with("*"))
path=path.substr(1,path.length());
@@ -833,6 +846,8 @@ void ProjectSettings::_autoload_edited() {
undo_redo->create_action("Toggle Autoload GlobalVar");
undo_redo->add_do_property(Globals::get_singleton(),base,path);
undo_redo->add_undo_property(Globals::get_singleton(),base,Globals::get_singleton()->get(base));
+ undo_redo->add_do_method(Globals::get_singleton(),"set_order",base,order); // keep order, as config order matters for these
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",base,order);
undo_redo->add_do_method(this,"_update_autoload");
undo_redo->add_undo_method(this,"_update_autoload");
undo_redo->add_do_method(this,"_settings_changed");
@@ -924,10 +939,12 @@ void ProjectSettings::_autoload_delete(Object *p_item,int p_column, int p_button
if (p_button==0) {
//delete
+ int order = Globals::get_singleton()->get_order(name);
undo_redo->create_action("Remove Autoload");
undo_redo->add_do_property(Globals::get_singleton(),name,Variant());
undo_redo->add_undo_property(Globals::get_singleton(),name,Globals::get_singleton()->get(name));
undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",name,true);
+ undo_redo->add_undo_method(Globals::get_singleton(),"set_order",name,order);
undo_redo->add_do_method(this,"_update_autoload");
undo_redo->add_undo_method(this,"_update_autoload");
undo_redo->add_do_method(this,"_settings_changed");
@@ -1375,9 +1392,9 @@ void ProjectSettings::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_save"),&ProjectSettings::_save);
ObjectTypeDB::bind_method(_MD("_action_add"),&ProjectSettings::_action_add);
ObjectTypeDB::bind_method(_MD("_action_adds"),&ProjectSettings::_action_adds);
- ObjectTypeDB::bind_method(_MD("_action_persist_toggle"),&ProjectSettings::_action_persist_toggle);
+ ObjectTypeDB::bind_method(_MD("_action_selected"),&ProjectSettings::_action_selected);
+ ObjectTypeDB::bind_method(_MD("_action_edited"),&ProjectSettings::_action_edited);
ObjectTypeDB::bind_method(_MD("_action_button_pressed"),&ProjectSettings::_action_button_pressed);
- ObjectTypeDB::bind_method(_MD("_action_rename"),&ProjectSettings::_action_rename);
ObjectTypeDB::bind_method(_MD("_update_actions"),&ProjectSettings::_update_actions);
ObjectTypeDB::bind_method(_MD("_wait_for_key"),&ProjectSettings::_wait_for_key);
ObjectTypeDB::bind_method(_MD("_add_item"),&ProjectSettings::_add_item);
@@ -1592,19 +1609,13 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
input_editor->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
input_editor->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 );
input_editor->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 );
- input_editor->connect("item_edited",this,"_action_persist_toggle");
+ input_editor->connect("item_edited",this,"_action_edited");
+ input_editor->connect("cell_selected",this,"_action_selected");
input_editor->connect("button_pressed",this,"_action_button_pressed");
popup_add = memnew( PopupMenu );
add_child(popup_add);
popup_add->connect("item_pressed",this,"_add_item");
- rename_action = memnew( EditorNameDialog );
- add_child(rename_action);
- rename_action->set_hide_on_ok(false);
- rename_action->set_size(Size2(200, 70));
- rename_action->set_title("Rename Input Action");
- rename_action->connect("name_confirmed", this,"_action_rename");
-
press_a_key = memnew( ConfirmationDialog );
press_a_key->set_focus_mode(FOCUS_ALL);
add_child(press_a_key);
diff --git a/tools/editor/project_settings.h b/tools/editor/project_settings.h
index b689340fdf..fd56fc1478 100644
--- a/tools/editor/project_settings.h
+++ b/tools/editor/project_settings.h
@@ -34,7 +34,6 @@
#include "optimized_save_dialog.h"
#include "undo_redo.h"
#include "editor_data.h"
-#include "editor_name_dialog.h"
//#include "project_export_settings.h"
class ProjectSettings : public AcceptDialog {
@@ -67,8 +66,6 @@ class ProjectSettings : public AcceptDialog {
Label *device_index_label;
MenuButton *popup_platform;
- EditorNameDialog *rename_action;
-
LineEdit *action_name;
Tree *input_editor;
bool setting;
@@ -111,11 +108,11 @@ class ProjectSettings : public AcceptDialog {
void _action_adds(String);
void _action_add();
- void _action_rename(const String& p_name);
void _device_input_add();
void _item_checked(const String& p_item, bool p_check);
- void _action_persist_toggle();
+ void _action_selected();
+ void _action_edited();
void _action_button_pressed(Object* p_obj, int p_column,int p_id);
void _wait_for_key(const InputEvent& p_event);
void _press_a_key_confirm();
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index 4b1b93ea6e..303604c2fc 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -714,7 +714,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty
RES r = v;
if (r.is_valid() && r->get_path().is_resource_file() && r->get_import_metadata().is_valid()) {
menu->add_separator();
- menu->add_icon_item(get_icon("Reload","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT);
+ menu->add_icon_item(get_icon("ReloadSmall","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT);
}
/*if (r.is_valid() && r->get_path().is_resource_file()) {
menu->set_item_tooltip(1,r->get_path());
@@ -2127,11 +2127,13 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
bool has_reload=false;
int found=-1;
+ bool is_disabled=false;
for(int i=0;i<item->get_button_count(1);i++) {
if (item->get_button_id(1,i)==3) {
found=i;
+ is_disabled=item->is_button_disabled(1,i);
break;
}
}
@@ -2149,7 +2151,7 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
bool changed = _is_property_different(v,vorig,usage);
- if ((found!=-1)!=changed) {
+ //if ((found!=-1 && !is_disabled)!=changed) {
if (changed) {
@@ -2158,11 +2160,9 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
}
- }
-
- }
-
+ //}
+ }
}
@@ -2176,10 +2176,20 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
}
}
+ //print_line("found: "+itos(found)+" has reload: "+itos(has_reload)+" is_disabled "+itos(is_disabled));
if (found!=-1 && !has_reload) {
- item->erase_button(1,found);
+
+ if (!is_disabled) {
+ item->erase_button(1,found);
+ if (item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) {
+ item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true);
+ }
+ }
} else if (found==-1 && has_reload) {
- item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
+ } else if (found!=-1 && has_reload && is_disabled) {
+ item->erase_button(1,found);
+ item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
}
}
@@ -2348,7 +2358,7 @@ void PropertyEditor::_refresh_item(TreeItem *p_item) {
if (!has_reload && found!=-1) {
p_item->erase_button(1,found);
} else if (has_reload && found==-1) {
- p_item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ p_item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
}
#endif
Dictionary d=p_item->get_metadata(0);
@@ -3092,7 +3102,9 @@ void PropertyEditor::update_tree() {
}
bool has_reload=false;
- if (_might_be_in_instance()) {
+
+ bool mbi = _might_be_in_instance();
+ if (mbi) {
Variant vorig;
Dictionary d=item->get_metadata(0);
@@ -3103,7 +3115,7 @@ void PropertyEditor::update_tree() {
if (_is_property_different(v,vorig,usage)) {
//print_line("FOR "+String(p.name)+" RELOAD WITH: "+String(v)+"("+Variant::get_type_name(v.get_type())+")=="+String(vorig)+"("+Variant::get_type_name(vorig.get_type())+")");
- item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
has_reload=true;
}
}
@@ -3115,11 +3127,16 @@ void PropertyEditor::update_tree() {
Variant orig_value;
if (scr->get_property_default_value(p.name,orig_value)) {
if (orig_value!=obj->get(p.name)) {
- item->add_button(1,get_icon("Reload","EditorIcons"),3);
+ item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
+ has_reload=true;
}
}
}
+ if (mbi && !has_reload && item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) {
+ item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true);
+ }
+
}
@@ -3180,6 +3197,9 @@ void PropertyEditor::_item_edited() {
TreeItem * item = tree->get_edited();
+ if (!item)
+ return; //it all happened too fast..
+
Dictionary d = item->get_metadata(0);
String name=d["name"];
@@ -3701,9 +3721,7 @@ PropertyEditor::PropertyEditor() {
capitalize_paths=true;
autoclear=false;
- tree->set_column_title(0,"Property");
- tree->set_column_title(1,"Value");
- tree->set_column_titles_visible(true);
+ tree->set_column_titles_visible(false);
keying=false;
read_only=false;
diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp
index 0260457c81..45eecacb6b 100644
--- a/tools/editor/scene_tree_editor.cpp
+++ b/tools/editor/scene_tree_editor.cpp
@@ -230,7 +230,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
return;
}
} else {
- part_of_subscene = get_scene_node()->get_scene_inherited_state().is_valid() && get_scene_node()->get_scene_inherited_state()->find_node_by_path(get_scene_node()->get_path_to(p_node))>=0;
+ part_of_subscene = p_node!=get_scene_node() && get_scene_node()->get_scene_inherited_state().is_valid() && get_scene_node()->get_scene_inherited_state()->find_node_by_path(get_scene_node()->get_path_to(p_node))>=0;
}
TreeItem *item = tree->create_item(p_parent);
@@ -658,6 +658,9 @@ void SceneTreeEditor::_renamed() {
new_name=n->get_name();
}
+ if (new_name==n->get_name())
+ return;
+
if (!undo_redo) {
n->set_name( new_name );
which->set_metadata(0,n->get_path());
@@ -844,7 +847,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open
add_child( tree );
tree->connect("cell_selected", this,"_selected_changed");
- tree->connect("item_edited", this,"_renamed");
+ tree->connect("item_edited", this,"_renamed",varray(),CONNECT_DEFERRED);
tree->connect("multi_selected",this,"_cell_multi_selected");
tree->connect("button_pressed",this,"_cell_button_pressed");
// tree->connect("item_edited", this,"_renamed",Vector<Variant>(),true);
diff --git a/tools/editor/settings_config_dialog.cpp b/tools/editor/settings_config_dialog.cpp
index ebbc488ff2..86a3ab7001 100644
--- a/tools/editor/settings_config_dialog.cpp
+++ b/tools/editor/settings_config_dialog.cpp
@@ -321,12 +321,12 @@ EditorSettingsDialog::EditorSettingsDialog() {
vbc->add_child(hbc);
hbc->add_child( memnew( Label("Plugin List: ")));
hbc->add_spacer();
- Button *load = memnew( Button );
- load->set_text("Load..");
+ //Button *load = memnew( Button );
+ //load->set_text("Load..");
+ //hbc->add_child(load);
Button *rescan = memnew( Button );
rescan_plugins=rescan;
rescan_plugins->connect("pressed",this,"_rescan_plugins");
- hbc->add_child(load);
hbc->add_child(rescan);
plugins = memnew( Tree );
MarginContainer *mc = memnew( MarginContainer);
diff --git a/tools/pe_bliss/README b/tools/pe_bliss/README
deleted file mode 100644
index d5d1355444..0000000000
--- a/tools/pe_bliss/README
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-
-Открытая бесплатная библиотека для работы с PE-файлами PE Bliss.
-Бесплатна к использованию, модификации и распространению.
-Автор: DX
-(c) DX 2011-2012, kaimi.ru
-
-Совместимость: Windows, Linux
-
-Возможности:
-[+] Создание PE или PE+ файла с нуля
-[+] Чтение 32-разрядных и 64-разрядных PE-файлов (PE, PE+) и единообразная работа с ними
-[+] Пересборка 32-разрядных и 64-разрядных PE-файлов
-[+] Работа с директориями и заголовками
-[+] Конвертирование адресов
-[+] Чтение и редактирование секций PE-файла
-[+] Чтение и редактирование таблицы импортов
-[+] Чтение и редактирование таблицы экспортов
-[+] Чтение и редактирование таблиц релокаций
-[+] Чтение и редактирование ресурсов
-[+] Чтение и редактирование TLS
-[+] Чтение и редактирование конфигурации образа (image config)
-[+] Чтение базовой информации .NET
-[+] Чтение и редактирование информации о привязанном импорте
-[+] Чтение директории исключений (только PE+)
-[+] Чтение отладочной директории с расширенной информацией
-[+] Вычисление энтропии
-[+] Изменение файлового выравнивания
-[+] Изменение базового адреса загрузки
-[+] Работа с DOS Stub'ом и Rich overlay
-[+] Высокоуровневое чтение ресурсов: картинки, иконки, курсоры, информация о версии, строковые таблицы, таблицы сообщений
-[+] Высокоуровневое редактирование ресурсов: картинки, иконки, курсоры, информация о версии
-
-[English]
-Open a free library for working with PE-file PE Bliss.
-Free to use, modify, and distribute.
-Author: DX
-(c) DX 2011-2012, kaimi.ru
-Compatibility: Windows, Linux
-
-### Capabilities:
-[+] Creation of PE or PE + file from scratch
-[+] Reading the 32-bit and 64-bit PE-file (PE, PE +) and uniform working with them
-[+] Rebuild 32-bit and 64-bit PE-files
-[+] Working with the directors and titles
-[+] Converting addresses
-[+] Reading and editing sections of PE-file
-[+] Reading and editing the import table
-[+] Reading and editing tables exports
-[+] Reading and editing tables relocations
-[+] Reading and editing resources
-[+] Reading and editing TLS
-[+] Reading and editing the configuration of the image (image config)
-[+] Reading data base .NET
-[+] Reading and editing information about tethered import
-[+] Read the directory exceptions (only PE +)
-[+] Read debug directories with extended information
-[+] The calculation of entropy
-[+] Changing file alignment
-[+] Change the base load address
-[+] Support of DOS Stub'om and Rich overlay
-[+] High-level reading resources: images, icons, cursors, version information, string tables, message table
-[+] High-level editing resources: images, icons, cursors, version information \ No newline at end of file
diff --git a/tools/pe_bliss/SCsub b/tools/pe_bliss/SCsub
deleted file mode 100644
index 34524f10ef..0000000000
--- a/tools/pe_bliss/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-Import('env')
-
-env.add_source_files(env.tool_sources,"*.cpp")
-
-Export('env')
diff --git a/tools/pe_bliss/entropy.cpp b/tools/pe_bliss/entropy.cpp
deleted file mode 100644
index acefa63e83..0000000000
--- a/tools/pe_bliss/entropy.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <cmath>
-#include "entropy.h"
-#include "utils.h"
-
-namespace pe_bliss
-{
-//Calculates entropy for PE image section
-double entropy_calculator::calculate_entropy(const section& s)
-{
- if(s.get_raw_data().empty()) //Don't count entropy for empty sections
- throw pe_exception("Section is empty", pe_exception::section_is_empty);
-
- return calculate_entropy(s.get_raw_data().data(), s.get_raw_data().length());
-}
-
-//Calculates entropy for istream (from current position of stream)
-double entropy_calculator::calculate_entropy(std::istream& file)
-{
- uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes
-
- if(file.bad())
- throw pe_exception("Stream is bad", pe_exception::stream_is_bad);
-
- std::streamoff pos = file.tellg();
-
- std::streamoff length = pe_utils::get_file_size(file);
- length -= file.tellg();
-
- if(!length) //Don't calculate entropy for empty buffers
- throw pe_exception("Data length is zero", pe_exception::data_is_empty);
-
- //Count bytes
- for(std::streamoff i = 0; i != length; ++i)
- ++byte_count[static_cast<unsigned char>(file.get())];
-
- file.seekg(pos);
-
- return calculate_entropy(byte_count, length);
-}
-
-//Calculates entropy for data block
-double entropy_calculator::calculate_entropy(const char* data, size_t length)
-{
- uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes
-
- if(!length) //Don't calculate entropy for empty buffers
- throw pe_exception("Data length is zero", pe_exception::data_is_empty);
-
- //Count bytes
- for(size_t i = 0; i != length; ++i)
- ++byte_count[static_cast<unsigned char>(data[i])];
-
- return calculate_entropy(byte_count, length);
-}
-
-//Calculates entropy for this PE file (only section data)
-double entropy_calculator::calculate_entropy(const pe_base& pe)
-{
- uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes
-
- size_t total_data_length = 0;
-
- //Count bytes for each section
- for(section_list::const_iterator it = pe.get_image_sections().begin(); it != pe.get_image_sections().end(); ++it)
- {
- const std::string& data = (*it).get_raw_data();
- size_t length = data.length();
- total_data_length += length;
- for(size_t i = 0; i != length; ++i)
- ++byte_count[static_cast<unsigned char>(data[i])];
- }
-
- return calculate_entropy(byte_count, total_data_length);
-}
-
-//Calculates entropy from bytes count
-double entropy_calculator::calculate_entropy(const uint32_t byte_count[256], std::streamoff total_length)
-{
- double entropy = 0.; //Entropy result value
- //Calculate entropy
- for(uint32_t i = 0; i < 256; ++i)
- {
- double temp = static_cast<double>(byte_count[i]) / total_length;
- if(temp > 0.)
- entropy += std::abs(temp * (std::log(temp) * pe_utils::log_2));
- }
-
- return entropy;
-}
-}
diff --git a/tools/pe_bliss/entropy.h b/tools/pe_bliss/entropy.h
deleted file mode 100644
index 7d225a3e32..0000000000
--- a/tools/pe_bliss/entropy.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <istream>
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-class entropy_calculator
-{
-public:
- //Calculates entropy for PE image section
- static double calculate_entropy(const section& s);
-
- //Calculates entropy for istream (from current position of stream)
- static double calculate_entropy(std::istream& file);
-
- //Calculates entropy for data block
- static double calculate_entropy(const char* data, size_t length);
-
- //Calculates entropy for this PE file (only section data)
- static double calculate_entropy(const pe_base& pe);
-
-private:
- entropy_calculator();
- entropy_calculator(const entropy_calculator&);
- entropy_calculator& operator=(const entropy_calculator&);
-
- //Calculates entropy from bytes count
- static double calculate_entropy(const uint32_t byte_count[256], std::streamoff total_length);
-};
-}
diff --git a/tools/pe_bliss/file_version_info.cpp b/tools/pe_bliss/file_version_info.cpp
deleted file mode 100644
index 3f2ba454b4..0000000000
--- a/tools/pe_bliss/file_version_info.cpp
+++ /dev/null
@@ -1,440 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "file_version_info.h"
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Default constructor
-file_version_info::file_version_info()
- :file_version_ms_(0), file_version_ls_(0),
- product_version_ms_(0), product_version_ls_(0),
- file_flags_(0),
- file_os_(0),
- file_type_(0), file_subtype_(0),
- file_date_ms_(0), file_date_ls_(0)
-{}
-
-//Constructor from Windows fixed version info structure
-file_version_info::file_version_info(const vs_fixedfileinfo& info)
- :file_version_ms_(info.dwFileVersionMS), file_version_ls_(info.dwFileVersionLS),
- product_version_ms_(info.dwProductVersionMS), product_version_ls_(info.dwProductVersionLS),
- file_flags_(info.dwFileFlags),
- file_os_(info.dwFileOS),
- file_type_(info.dwFileType), file_subtype_(info.dwFileSubtype),
- file_date_ms_(info.dwFileDateMS), file_date_ls_(info.dwFileDateLS)
-{}
-
-//Returns true if file is debug-built
-bool file_version_info::is_debug() const
-{
- return file_flags_ & vs_ff_debug ? true : false;
-}
-
-//Returns true if file is release-built
-bool file_version_info::is_prerelease() const
-{
- return file_flags_ & vs_ff_prerelease ? true : false;
-}
-
-//Returns true if file is patched
-bool file_version_info::is_patched() const
-{
- return file_flags_ & vs_ff_patched ? true : false;
-}
-
-//Returns true if private build
-bool file_version_info::is_private_build() const
-{
- return file_flags_ & vs_ff_privatebuild ? true : false;
-}
-
-//Returns true if special build
-bool file_version_info::is_special_build() const
-{
- return file_flags_ & vs_ff_specialbuild ? true : false;
-}
-
-//Returns true if info inferred
-bool file_version_info::is_info_inferred() const
-{
- return file_flags_ & vs_ff_infoinferred ? true : false;
-}
-
-//Retuens file flags (raw DWORD)
-uint32_t file_version_info::get_file_flags() const
-{
- return file_flags_;
-}
-
-//Returns file version most significant DWORD
-uint32_t file_version_info::get_file_version_ms() const
-{
- return file_version_ms_;
-}
-
-//Returns file version least significant DWORD
-uint32_t file_version_info::get_file_version_ls() const
-{
- return file_version_ls_;
-}
-
-//Returns product version most significant DWORD
-uint32_t file_version_info::get_product_version_ms() const
-{
- return product_version_ms_;
-}
-
-//Returns product version least significant DWORD
-uint32_t file_version_info::get_product_version_ls() const
-{
- return product_version_ls_;
-}
-
-//Returns file OS type (raw DWORD)
-uint32_t file_version_info::get_file_os_raw() const
-{
- return file_os_;
-}
-
-//Returns file OS type
-file_version_info::file_os_type file_version_info::get_file_os() const
-{
- //Determine file operation system type
- switch(file_os_)
- {
- case vos_dos:
- return file_os_dos;
-
- case vos_os216:
- return file_os_os216;
-
- case vos_os232:
- return file_os_os232;
-
- case vos_nt:
- return file_os_nt;
-
- case vos_wince:
- return file_os_wince;
-
- case vos__windows16:
- return file_os_win16;
-
- case vos__pm16:
- return file_os_pm16;
-
- case vos__pm32:
- return file_os_pm32;
-
- case vos__windows32:
- return file_os_win32;
-
- case vos_dos_windows16:
- return file_os_dos_win16;
-
- case vos_dos_windows32:
- return file_os_dos_win32;
-
- case vos_os216_pm16:
- return file_os_os216_pm16;
-
- case vos_os232_pm32:
- return file_os_os232_pm32;
-
- case vos_nt_windows32:
- return file_os_nt_win32;
- }
-
- return file_os_unknown;
-}
-
-//Returns file type (raw DWORD)
-uint32_t file_version_info::get_file_type_raw() const
-{
- return file_type_;
-}
-
-//Returns file type
-file_version_info::file_type file_version_info::get_file_type() const
-{
- //Determine file type
- switch(file_type_)
- {
- case vft_app:
- return file_type_application;
-
- case vft_dll:
- return file_type_dll;
-
- case vft_drv:
- return file_type_driver;
-
- case vft_font:
- return file_type_font;
-
- case vft_vxd:
- return file_type_vxd;
-
- case vft_static_lib:
- return file_type_static_lib;
- }
-
- return file_type_unknown;
-}
-
-//Returns file subtype (usually non-zero for drivers and fonts)
-uint32_t file_version_info::get_file_subtype() const
-{
- return file_subtype_;
-}
-
-//Returns file date most significant DWORD
-uint32_t file_version_info::get_file_date_ms() const
-{
- return file_date_ms_;
-}
-
-//Returns file date least significant DWORD
-uint32_t file_version_info::get_file_date_ls() const
-{
- return file_date_ls_;
-}
-
-//Helper to set file flag
-void file_version_info::set_file_flag(uint32_t flag)
-{
- file_flags_ |= flag;
-}
-
-//Helper to clear file flag
-void file_version_info::clear_file_flag(uint32_t flag)
-{
- file_flags_ &= ~flag;
-}
-
-//Helper to set or clear file flag
-void file_version_info::set_file_flag(uint32_t flag, bool set_flag)
-{
- set_flag ? set_file_flag(flag) : clear_file_flag(flag);
-}
-
-//Sets if file is debug-built
-void file_version_info::set_debug(bool debug)
-{
- set_file_flag(vs_ff_debug, debug);
-}
-
-//Sets if file is prerelease
-void file_version_info::set_prerelease(bool prerelease)
-{
- set_file_flag(vs_ff_prerelease, prerelease);
-}
-
-//Sets if file is patched
-void file_version_info::set_patched(bool patched)
-{
- set_file_flag(vs_ff_patched, patched);
-}
-
-//Sets if private build
-void file_version_info::set_private_build(bool private_build)
-{
- set_file_flag(vs_ff_privatebuild, private_build);
-}
-
-//Sets if special build
-void file_version_info::set_special_build(bool special_build)
-{
- set_file_flag(vs_ff_specialbuild, special_build);
-}
-
-//Sets if info inferred
-void file_version_info::set_info_inferred(bool info_inferred)
-{
- set_file_flag(vs_ff_infoinferred, info_inferred);
-}
-
-//Sets flags (raw DWORD)
-void file_version_info::set_file_flags(uint32_t file_flags)
-{
- file_flags_ = file_flags;
-}
-
-//Sets file version most significant DWORD
-void file_version_info::set_file_version_ms(uint32_t file_version_ms)
-{
- file_version_ms_ = file_version_ms;
-}
-
-//Sets file version least significant DWORD
-void file_version_info::set_file_version_ls(uint32_t file_version_ls)
-{
- file_version_ls_ = file_version_ls;
-}
-
-//Sets product version most significant DWORD
-void file_version_info::set_product_version_ms(uint32_t product_version_ms)
-{
- product_version_ms_ = product_version_ms;
-}
-
-//Sets product version least significant DWORD
-void file_version_info::set_product_version_ls(uint32_t product_version_ls)
-{
- product_version_ls_ = product_version_ls;
-}
-
-//Sets file OS type (raw DWORD)
-void file_version_info::set_file_os_raw(uint32_t file_os)
-{
- file_os_ = file_os;
-}
-
-//Sets file OS type
-void file_version_info::set_file_os(file_os_type file_os)
-{
- //Determine file operation system type
- switch(file_os)
- {
- case file_os_dos:
- file_os_ = vos_dos;
- return;
-
- case file_os_os216:
- file_os_ = vos_os216;
- return;
-
- case file_os_os232:
- file_os_ = vos_os232;
- return;
-
- case file_os_nt:
- file_os_ = vos_nt;
- return;
-
- case file_os_wince:
- file_os_ = vos_wince;
- return;
-
- case file_os_win16:
- file_os_ = vos__windows16;
- return;
-
- case file_os_pm16:
- file_os_ = vos__pm16;
- return;
-
- case file_os_pm32:
- file_os_ = vos__pm32;
- return;
-
- case file_os_win32:
- file_os_ = vos__windows32;
- return;
-
- case file_os_dos_win16:
- file_os_ = vos_dos_windows16;
- return;
-
- case file_os_dos_win32:
- file_os_ = vos_dos_windows32;
- return;
-
- case file_os_os216_pm16:
- file_os_ = vos_os216_pm16;
- return;
-
- case file_os_os232_pm32:
- file_os_ = vos_os232_pm32;
- return;
-
- case file_os_nt_win32:
- file_os_ = vos_nt_windows32;
- return;
-
- default:
- return;
- }
-}
-
-//Sets file type (raw DWORD)
-void file_version_info::set_file_type_raw(uint32_t file_type)
-{
- file_type_ = file_type;
-}
-
-//Sets file type
-void file_version_info::set_file_type(file_type file_type)
-{
- //Determine file type
- switch(file_type)
- {
- case file_type_application:
- file_type_ = vft_app;
- return;
-
- case file_type_dll:
- file_type_ = vft_dll;
- return;
-
- case file_type_driver:
- file_type_ = vft_drv;
- return;
-
- case file_type_font:
- file_type_ = vft_font;
- return;
-
- case file_type_vxd:
- file_type_ = vft_vxd;
- return;
-
- case file_type_static_lib:
- file_type_ = vft_static_lib;
- return;
-
- default:
- return;
- }
-}
-
-//Sets file subtype (usually non-zero for drivers and fonts)
-void file_version_info::set_file_subtype(uint32_t file_subtype)
-{
- file_subtype_ = file_subtype;
-}
-
-//Sets file date most significant DWORD
-void file_version_info::set_file_date_ms(uint32_t file_date_ms)
-{
- file_date_ms_ = file_date_ms;
-}
-
-//Sets file date least significant DWORD
-void file_version_info::set_file_date_ls(uint32_t file_date_ls)
-{
- file_date_ls_ = file_date_ls;
-}
-}
diff --git a/tools/pe_bliss/file_version_info.h b/tools/pe_bliss/file_version_info.h
deleted file mode 100644
index d898351ba1..0000000000
--- a/tools/pe_bliss/file_version_info.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include <map>
-#include "stdint_defs.h"
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-//Structure representing fixed file version info
-class file_version_info
-{
-public:
- //Enumeration of file operating system types
- enum file_os_type
- {
- file_os_unknown,
- file_os_dos,
- file_os_os216,
- file_os_os232,
- file_os_nt,
- file_os_wince,
- file_os_win16,
- file_os_pm16,
- file_os_pm32,
- file_os_win32,
- file_os_dos_win16,
- file_os_dos_win32,
- file_os_os216_pm16,
- file_os_os232_pm32,
- file_os_nt_win32
- };
-
- //Enumeration of file types
- enum file_type
- {
- file_type_unknown,
- file_type_application,
- file_type_dll,
- file_type_driver,
- file_type_font,
- file_type_vxd,
- file_type_static_lib
- };
-
-public:
- //Default constructor
- file_version_info();
- //Constructor from Windows fixed version info structure
- explicit file_version_info(const pe_win::vs_fixedfileinfo& info);
-
-public: //Getters
- //Returns true if file is debug-built
- bool is_debug() const;
- //Returns true if file is prerelease
- bool is_prerelease() const;
- //Returns true if file is patched
- bool is_patched() const;
- //Returns true if private build
- bool is_private_build() const;
- //Returns true if special build
- bool is_special_build() const;
- //Returns true if info inferred
- bool is_info_inferred() const;
- //Retuens file flags (raw DWORD)
- uint32_t get_file_flags() const;
-
- //Returns file version most significant DWORD
- uint32_t get_file_version_ms() const;
- //Returns file version least significant DWORD
- uint32_t get_file_version_ls() const;
- //Returns product version most significant DWORD
- uint32_t get_product_version_ms() const;
- //Returns product version least significant DWORD
- uint32_t get_product_version_ls() const;
-
- //Returns file OS type (raw DWORD)
- uint32_t get_file_os_raw() const;
- //Returns file OS type
- file_os_type get_file_os() const;
-
- //Returns file type (raw DWORD)
- uint32_t get_file_type_raw() const;
- //Returns file type
- file_type get_file_type() const;
-
- //Returns file subtype (usually non-zero for drivers and fonts)
- uint32_t get_file_subtype() const;
-
- //Returns file date most significant DWORD
- uint32_t get_file_date_ms() const;
- //Returns file date least significant DWORD
- uint32_t get_file_date_ls() const;
-
- //Returns file version string
- template<typename T>
- const std::basic_string<T> get_file_version_string() const
- {
- return get_version_string<T>(file_version_ms_, file_version_ls_);
- }
-
- //Returns product version string
- template<typename T>
- const std::basic_string<T> get_product_version_string() const
- {
- return get_version_string<T>(product_version_ms_, product_version_ls_);
- }
-
-public: //Setters
- //Sets if file is debug-built
- void set_debug(bool debug);
- //Sets if file is prerelease
- void set_prerelease(bool prerelease);
- //Sets if file is patched
- void set_patched(bool patched);
- //Sets if private build
- void set_private_build(bool private_build);
- //Sets if special build
- void set_special_build(bool special_build);
- //Sets if info inferred
- void set_info_inferred(bool info_inferred);
- //Sets flags (raw DWORD)
- void set_file_flags(uint32_t file_flags);
-
- //Sets file version most significant DWORD
- void set_file_version_ms(uint32_t file_version_ms);
- //Sets file version least significant DWORD
- void set_file_version_ls(uint32_t file_version_ls);
- //Sets product version most significant DWORD
- void set_product_version_ms(uint32_t product_version_ms);
- //Sets product version least significant DWORD
- void set_product_version_ls(uint32_t product_version_ls);
-
- //Sets file OS type (raw DWORD)
- void set_file_os_raw(uint32_t file_os);
- //Sets file OS type
- void set_file_os(file_os_type file_os);
-
- //Sets file type (raw DWORD)
- void set_file_type_raw(uint32_t file_type);
- //Sets file type
- void set_file_type(file_type file_type);
-
- //Sets file subtype (usually non-zero for drivers and fonts)
- void set_file_subtype(uint32_t file_subtype);
-
- //Sets file date most significant DWORD
- void set_file_date_ms(uint32_t file_date_ms);
- //Sets file date least significant DWORD
- void set_file_date_ls(uint32_t file_date_ls);
-
-private:
- //Helper to convert version DWORDs to string
- template<typename T>
- static const std::basic_string<T> get_version_string(uint32_t ms, uint32_t ls)
- {
- std::basic_stringstream<T> ss;
- ss << (ms >> 16) << static_cast<T>(L'.')
- << (ms & 0xFFFF) << static_cast<T>(L'.')
- << (ls >> 16) << static_cast<T>(L'.')
- << (ls & 0xFFFF);
- return ss.str();
- }
-
- //Helper to set file flag
- void set_file_flag(uint32_t flag);
- //Helper to clear file flag
- void clear_file_flag(uint32_t flag);
- //Helper to set or clear file flag
- void set_file_flag(uint32_t flag, bool set_flag);
-
- uint32_t file_version_ms_, file_version_ls_,
- product_version_ms_, product_version_ls_;
- uint32_t file_flags_;
- uint32_t file_os_;
- uint32_t file_type_, file_subtype_;
- uint32_t file_date_ms_, file_date_ls_;
-};
-}
diff --git a/tools/pe_bliss/message_table.cpp b/tools/pe_bliss/message_table.cpp
deleted file mode 100644
index 909be5d494..0000000000
--- a/tools/pe_bliss/message_table.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "message_table.h"
-#include "utils.h"
-
-namespace pe_bliss
-{
-//Default constructor
-message_table_item::message_table_item()
- :unicode_(false)
-{}
-
-//Constructor from ANSI string
-message_table_item::message_table_item(const std::string& str)
- :unicode_(false), ansi_str_(str)
-{
- pe_utils::strip_nullbytes(ansi_str_);
-}
-
-//Constructor from UNICODE string
-message_table_item::message_table_item(const std::wstring& str)
- :unicode_(true), unicode_str_(str)
-{
- pe_utils::strip_nullbytes(unicode_str_);
-}
-
-//Returns true if contained string is unicode
-bool message_table_item::is_unicode() const
-{
- return unicode_;
-}
-
-//Returns ANSI string
-const std::string& message_table_item::get_ansi_string() const
-{
- return ansi_str_;
-}
-
-//Returns UNICODE string
-const std::wstring& message_table_item::get_unicode_string() const
-{
- return unicode_str_;
-}
-
-//Sets ANSI string (clears UNICODE one)
-void message_table_item::set_string(const std::string& str)
-{
- ansi_str_ = str;
- pe_utils::strip_nullbytes(ansi_str_);
- unicode_str_.clear();
- unicode_ = false;
-}
-
-//Sets UNICODE string (clears ANSI one)
-void message_table_item::set_string(const std::wstring& str)
-{
- unicode_str_ = str;
- pe_utils::strip_nullbytes(unicode_str_);
- ansi_str_.clear();
- unicode_ = true;
-}
-}
diff --git a/tools/pe_bliss/message_table.h b/tools/pe_bliss/message_table.h
deleted file mode 100644
index 5a3feb32c1..0000000000
--- a/tools/pe_bliss/message_table.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include <map>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-//Structure representing message table string
-class message_table_item
-{
-public:
- //Default constructor
- message_table_item();
- //Constructors from ANSI and UNICODE strings
- explicit message_table_item(const std::string& str);
- explicit message_table_item(const std::wstring& str);
-
- //Returns true if string is UNICODE
- bool is_unicode() const;
- //Returns ANSI string
- const std::string& get_ansi_string() const;
- //Returns UNICODE string
- const std::wstring& get_unicode_string() const;
-
-public:
- //Sets ANSI or UNICODE string
- void set_string(const std::string& str);
- void set_string(const std::wstring& str);
-
-private:
- bool unicode_;
- std::string ansi_str_;
- std::wstring unicode_str_;
-};
-}
diff --git a/tools/pe_bliss/pe_base.cpp b/tools/pe_bliss/pe_base.cpp
deleted file mode 100644
index 97baa17cb3..0000000000
--- a/tools/pe_bliss/pe_base.cpp
+++ /dev/null
@@ -1,1680 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string>
-#include <vector>
-#include <istream>
-#include <ostream>
-#include <algorithm>
-#include <cmath>
-#include <set>
-#include <string.h>
-#include "pe_exception.h"
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Constructor
-pe_base::pe_base(std::istream& file, const pe_properties& props, bool read_debug_raw_data)
-{
- props_ = props.duplicate().release();
-
- //Save istream state
- std::ios_base::iostate state = file.exceptions();
- std::streamoff old_offset = file.tellg();
-
- try
- {
- file.exceptions(std::ios::goodbit);
- //Read DOS header, PE headers and section data
- read_dos_header(file);
- read_pe(file, read_debug_raw_data);
- }
- catch(const std::exception&)
- {
- //If something went wrong, restore istream state
- file.seekg(old_offset);
- file.exceptions(state);
- file.clear();
- //Rethrow
- throw;
- }
-
- //Restore istream state
- file.seekg(old_offset);
- file.exceptions(state);
- file.clear();
-}
-
-pe_base::pe_base(const pe_properties& props, uint32_t section_alignment, bool dll, uint16_t subsystem)
-{
- props_ = props.duplicate().release();
- props_->create_pe(section_alignment, subsystem);
-
- has_overlay_ = false;
- memset(&dos_header_, 0, sizeof(dos_header_));
-
- dos_header_.e_magic = 0x5A4D; //"MZ"
- //Magic numbers from MSVC++ build
- dos_header_.e_maxalloc = 0xFFFF;
- dos_header_.e_cblp = 0x90;
- dos_header_.e_cp = 3;
- dos_header_.e_cparhdr = 4;
- dos_header_.e_sp = 0xB8;
- dos_header_.e_lfarlc = 64;
-
- set_characteristics(image_file_executable_image | image_file_relocs_stripped);
-
- if(get_pe_type() == pe_type_32)
- set_characteristics_flags(image_file_32bit_machine);
-
- if(dll)
- set_characteristics_flags(image_file_dll);
-
- set_subsystem_version(5, 1); //WinXP
- set_os_version(5, 1); //WinXP
-}
-
-pe_base::pe_base(const pe_base& pe)
- :dos_header_(pe.dos_header_),
- rich_overlay_(pe.rich_overlay_),
- sections_(pe.sections_),
- has_overlay_(pe.has_overlay_),
- full_headers_data_(pe.full_headers_data_),
- debug_data_(pe.debug_data_),
- props_(0)
-{
- props_ = pe.props_->duplicate().release();
-}
-
-pe_base& pe_base::operator=(const pe_base& pe)
-{
- dos_header_ = pe.dos_header_;
- rich_overlay_ = pe.rich_overlay_;
- sections_ = pe.sections_;
- has_overlay_ = pe.has_overlay_;
- full_headers_data_ = pe.full_headers_data_;
- debug_data_ = pe.debug_data_;
- delete props_;
- props_ = 0;
- props_ = pe.props_->duplicate().release();
-
- return *this;
-}
-
-pe_base::~pe_base()
-{
- delete props_;
-}
-
-//Returns dos header
-const image_dos_header& pe_base::get_dos_header() const
-{
- return dos_header_;
-}
-
-//Returns dos header
-image_dos_header& pe_base::get_dos_header()
-{
- return dos_header_;
-}
-
-//Returns PE headers start position (e_lfanew)
-int32_t pe_base::get_pe_header_start() const
-{
- return dos_header_.e_lfanew;
-}
-
-//Strips MSVC stub overlay
-void pe_base::strip_stub_overlay()
-{
- rich_overlay_.clear();
-}
-
-//Fills MSVC stub overlay with character c
-void pe_base::fill_stub_overlay(char c)
-{
- if(rich_overlay_.length())
- rich_overlay_.assign(rich_overlay_.length(), c);
-}
-
-//Sets stub MSVS overlay
-void pe_base::set_stub_overlay(const std::string& data)
-{
- rich_overlay_ = data;
-}
-
-//Returns stub overlay
-const std::string& pe_base::get_stub_overlay() const
-{
- return rich_overlay_;
-}
-
-//Realigns all sections
-void pe_base::realign_all_sections()
-{
- for(unsigned int i = 0; i < sections_.size(); i++)
- realign_section(i);
-}
-
-//Returns number of sections from PE header
-uint16_t pe_base::get_number_of_sections() const
-{
- return props_->get_number_of_sections();
-}
-
-//Updates number of sections in PE header
-uint16_t pe_base::update_number_of_sections()
-{
- uint16_t new_number = static_cast<uint16_t>(sections_.size());
- props_->set_number_of_sections(new_number);
- return new_number;
-}
-
-//Returns section alignment
-uint32_t pe_base::get_section_alignment() const
-{
- return props_->get_section_alignment();
-}
-
-//Returns image sections list
-section_list& pe_base::get_image_sections()
-{
- return sections_;
-}
-
-//Returns image sections list
-const section_list& pe_base::get_image_sections() const
-{
- return sections_;
-}
-
-//Realigns section by index
-void pe_base::realign_section(uint32_t index)
-{
- //Check index
- if(sections_.size() <= index)
- throw pe_exception("Section not found", pe_exception::section_not_found);
-
- //Get section iterator
- section_list::iterator it = sections_.begin() + index;
- section& s = *it;
-
- //Calculate, how many null bytes we have in the end of raw section data
- std::size_t strip = 0;
- for(std::size_t i = (*it).get_raw_data().length(); i >= 1; --i)
- {
- if(s.get_raw_data()[i - 1] == 0)
- strip++;
- else
- break;
- }
-
- if(it == sections_.end() - 1) //If we're realigning the last section
- {
- //We can strip ending null bytes
- s.set_size_of_raw_data(static_cast<uint32_t>(s.get_raw_data().length() - strip));
- s.get_raw_data().resize(s.get_raw_data().length() - strip, 0);
- }
- else
- {
- //Else just set size of raw data
- uint32_t raw_size_aligned = s.get_aligned_raw_size(get_file_alignment());
- s.set_size_of_raw_data(raw_size_aligned);
- s.get_raw_data().resize(raw_size_aligned, 0);
- }
-}
-
-//Returns file alignment
-uint32_t pe_base::get_file_alignment() const
-{
- return props_->get_file_alignment();
-}
-
-//Sets file alignment
-void pe_base::set_file_alignment(uint32_t alignment)
-{
- //Check alignment
- if(alignment < minimum_file_alignment)
- throw pe_exception("File alignment can't be less than 512", pe_exception::incorrect_file_alignment);
-
- if(!pe_utils::is_power_of_2(alignment))
- throw pe_exception("File alignment must be a power of 2", pe_exception::incorrect_file_alignment);
-
- if(alignment > get_section_alignment())
- throw pe_exception("File alignment must be <= section alignment", pe_exception::incorrect_file_alignment);
-
- //Set file alignment without any additional checks
- set_file_alignment_unchecked(alignment);
-}
-
-//Returns size of image
-uint32_t pe_base::get_size_of_image() const
-{
- return props_->get_size_of_image();
-}
-
-//Returns image entry point
-uint32_t pe_base::get_ep() const
-{
- return props_->get_ep();
-}
-
-//Sets image entry point (just a value of PE header)
-void pe_base::set_ep(uint32_t new_ep)
-{
- props_->set_ep(new_ep);
-}
-
-//Returns number of RVA and sizes (number of DATA_DIRECTORY entries)
-uint32_t pe_base::get_number_of_rvas_and_sizes() const
-{
- return props_->get_number_of_rvas_and_sizes();
-}
-
-//Sets number of RVA and sizes (number of DATA_DIRECTORY entries)
-void pe_base::set_number_of_rvas_and_sizes(uint32_t number)
-{
- props_->set_number_of_rvas_and_sizes(number);
-}
-
-//Returns PE characteristics
-uint16_t pe_base::get_characteristics() const
-{
- return props_->get_characteristics();
-}
-
-//Sets PE characteristics (a value inside header)
-void pe_base::set_characteristics(uint16_t ch)
-{
- props_->set_characteristics(ch);
-}
-
-//Returns section from RVA
-section& pe_base::section_from_rva(uint32_t rva)
-{
- //Search for section
- for(section_list::iterator i = sections_.begin(); i != sections_.end(); ++i)
- {
- section& s = *i;
- //Return section if found
- if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()))
- return s;
- }
-
- throw pe_exception("No section found by presented address", pe_exception::no_section_found);
-}
-
-//Returns section from RVA
-const section& pe_base::section_from_rva(uint32_t rva) const
-{
- //Search for section
- for(section_list::const_iterator i = sections_.begin(); i != sections_.end(); ++i)
- {
- const section& s = *i;
- //Return section if found
- if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()))
- return s;
- }
-
- throw pe_exception("No section found by presented address", pe_exception::no_section_found);
-}
-
-//Returns section from directory ID
-section& pe_base::section_from_directory(uint32_t directory_id)
-{
- return section_from_rva(get_directory_rva(directory_id));
-}
-
-//Returns section from directory ID
-const section& pe_base::section_from_directory(uint32_t directory_id) const
-{
- return section_from_rva(get_directory_rva(directory_id));
-}
-
-//Sets section virtual size (actual for the last one of this PE or for unbound section)
-void pe_base::set_section_virtual_size(section& s, uint32_t vsize)
-{
- //Check if we're changing virtual size of the last section
- //Of course, we can change virtual size of section that's not bound to this PE file
- if(sections_.empty() || std::find_if(sections_.begin(), sections_.end() - 1, section_ptr_finder(s)) != sections_.end() - 1)
- throw pe_exception("Can't change virtual size of any section, except last one", pe_exception::error_changing_section_virtual_size);
-
- //If we're setting virtual size to zero
- if(vsize == 0)
- {
- //Check if section is empty
- if(s.empty())
- throw pe_exception("Cannot set virtual size of empty section to zero", pe_exception::error_changing_section_virtual_size);
-
- //Set virtual size equal to aligned size of raw data
- s.set_virtual_size(s.get_size_of_raw_data());
- }
- else
- {
- s.set_virtual_size(vsize);
- }
-
- //Update image size if we're changing virtual size for the last section of this PE
- if(!sections_.empty() || &s == &(*(sections_.end() - 1)))
- update_image_size();
-}
-
-//Expands section raw or virtual size to hold data from specified RVA with specified size
-//Section must be free (not bound to any image)
-//or the last section of this image
-bool pe_base::expand_section(section& s, uint32_t needed_rva, uint32_t needed_size, section_expand_type expand)
-{
- //Check if we're changing the last section
- //Of course, we can change the section that's not bound to this PE file
- if(sections_.empty() || std::find_if(sections_.begin(), sections_.end() - 1, section_ptr_finder(s)) != sections_.end() - 1)
- throw pe_exception("Can't expand any section, except last one", pe_exception::error_expanding_section);
-
- //Check if we should expand our section
- if(expand == expand_section_raw && section_data_length_from_rva(s, needed_rva, section_data_raw) < needed_size)
- {
- //Expand section raw data
- s.get_raw_data().resize(needed_rva - s.get_virtual_address() + needed_size);
- recalculate_section_sizes(s, false);
- return true;
- }
- else if(expand == expand_section_virtual && section_data_length_from_rva(s, needed_rva, section_data_virtual) < needed_size)
- {
- //Expand section virtual data
- set_section_virtual_size(s, needed_rva - s.get_virtual_address() + needed_size);
- return true;
- }
-
- return false;
-}
-
-//Updates image virtual size
-void pe_base::update_image_size()
-{
- //Write virtual size of image to headers
- if(!sections_.empty())
- set_size_of_image(sections_.back().get_virtual_address() + sections_.back().get_aligned_virtual_size(get_section_alignment()));
- else
- set_size_of_image(get_size_of_headers());
-}
-
-//Returns checksum of PE file from header
-uint32_t pe_base::get_checksum() const
-{
- return props_->get_checksum();
-}
-
-//Sets checksum of PE file
-void pe_base::set_checksum(uint32_t checksum)
-{
- props_->set_checksum(checksum);
-}
-
-//Returns timestamp of PE file from header
-uint32_t pe_base::get_time_date_stamp() const
-{
- return props_->get_time_date_stamp();
-}
-
-//Sets timestamp of PE file
-void pe_base::set_time_date_stamp(uint32_t timestamp)
-{
- props_->set_time_date_stamp(timestamp);
-}
-
-//Returns Machine field value of PE file from header
-uint16_t pe_base::get_machine() const
-{
- return props_->get_machine();
-}
-
-//Sets Machine field value of PE file
-void pe_base::set_machine(uint16_t machine)
-{
- props_->set_machine(machine);
-}
-
-//Prepares section before attaching it
-void pe_base::prepare_section(section& s)
-{
- //Calculate its size of raw data
- s.set_size_of_raw_data(static_cast<uint32_t>(pe_utils::align_up(s.get_raw_data().length(), get_file_alignment())));
-
- //Check section virtual and raw size
- if(!s.get_size_of_raw_data() && !s.get_virtual_size())
- throw pe_exception("Virtual and Physical sizes of section can't be 0 at the same time", pe_exception::zero_section_sizes);
-
- //If section virtual size is zero
- if(!s.get_virtual_size())
- {
- s.set_virtual_size(s.get_size_of_raw_data());
- }
- else
- {
- //Else calculate its virtual size
- s.set_virtual_size(
- std::max<uint32_t>(pe_utils::align_up(s.get_size_of_raw_data(), get_file_alignment()),
- pe_utils::align_up(s.get_virtual_size(), get_section_alignment())));
- }
-}
-
-//Adds section to image
-section& pe_base::add_section(section s)
-{
- if(sections_.size() >= maximum_number_of_sections)
- throw pe_exception("Maximum number of sections has been reached", pe_exception::no_more_sections_can_be_added);
-
- //Prepare section before adding it
- prepare_section(s);
-
- //Calculate section virtual address
- if(!sections_.empty())
- {
- s.set_virtual_address(pe_utils::align_up(sections_.back().get_virtual_address() + sections_.back().get_aligned_virtual_size(get_section_alignment()), get_section_alignment()));
-
- //We should align last section raw size, if it wasn't aligned
- section& last = sections_.back();
- last.set_size_of_raw_data(static_cast<uint32_t>(pe_utils::align_up(last.get_raw_data().length(), get_file_alignment())));
- }
- else
- {
- s.set_virtual_address(
- s.get_virtual_address() == 0
- ? pe_utils::align_up(get_size_of_headers(), get_section_alignment())
- : pe_utils::align_up(s.get_virtual_address(), get_section_alignment()));
- }
-
- //Add section to the end of section list
- sections_.push_back(s);
- //Set number of sections in PE header
- set_number_of_sections(static_cast<uint16_t>(sections_.size()));
- //Recalculate virtual size of image
- set_size_of_image(get_size_of_image() + s.get_aligned_virtual_size(get_section_alignment()));
- //Return last section
- return sections_.back();
-}
-
-//Returns true if sectios "s" is already attached to this PE file
-bool pe_base::section_attached(const section& s) const
-{
- return sections_.end() != std::find_if(sections_.begin(), sections_.end(), section_ptr_finder(s));
-}
-
-//Returns true if directory exists
-bool pe_base::directory_exists(uint32_t id) const
-{
- return props_->directory_exists(id);
-}
-
-//Removes directory
-void pe_base::remove_directory(uint32_t id)
-{
- props_->remove_directory(id);
-}
-
-//Returns directory RVA
-uint32_t pe_base::get_directory_rva(uint32_t id) const
-{
- return props_->get_directory_rva(id);
-}
-
-//Returns directory size
-uint32_t pe_base::get_directory_size(uint32_t id) const
-{
- return props_->get_directory_size(id);
-}
-
-//Sets directory RVA (just a value of PE header, no moving occurs)
-void pe_base::set_directory_rva(uint32_t id, uint32_t rva)
-{
- return props_->set_directory_rva(id, rva);
-}
-
-//Sets directory size (just a value of PE header, no moving occurs)
-void pe_base::set_directory_size(uint32_t id, uint32_t size)
-{
- return props_->set_directory_size(id, size);
-}
-
-//Strips only zero DATA_DIRECTORY entries to count = min_count
-//Returns resulting number of data directories
-//strip_iat_directory - if true, even not empty IAT directory will be stripped
-uint32_t pe_base::strip_data_directories(uint32_t min_count, bool strip_iat_directory)
-{
- return props_->strip_data_directories(min_count, strip_iat_directory);
-}
-
-//Returns true if image has import directory
-bool pe_base::has_imports() const
-{
- return directory_exists(image_directory_entry_import);
-}
-
-//Returns true if image has export directory
-bool pe_base::has_exports() const
-{
- return directory_exists(image_directory_entry_export);
-}
-
-//Returns true if image has resource directory
-bool pe_base::has_resources() const
-{
- return directory_exists(image_directory_entry_resource);
-}
-
-//Returns true if image has security directory
-bool pe_base::has_security() const
-{
- return directory_exists(image_directory_entry_security);
-}
-
-//Returns true if image has relocations
-bool pe_base::has_reloc() const
-{
- return directory_exists(image_directory_entry_basereloc) && !(get_characteristics() & image_file_relocs_stripped);
-}
-
-//Returns true if image has TLS directory
-bool pe_base::has_tls() const
-{
- return directory_exists(image_directory_entry_tls);
-}
-
-//Returns true if image has config directory
-bool pe_base::has_config() const
-{
- return directory_exists(image_directory_entry_load_config);
-}
-
-//Returns true if image has bound import directory
-bool pe_base::has_bound_import() const
-{
- return directory_exists(image_directory_entry_bound_import);
-}
-
-//Returns true if image has delay import directory
-bool pe_base::has_delay_import() const
-{
- return directory_exists(image_directory_entry_delay_import);
-}
-
-//Returns true if image has COM directory
-bool pe_base::is_dotnet() const
-{
- return directory_exists(image_directory_entry_com_descriptor);
-}
-
-//Returns true if image has exception directory
-bool pe_base::has_exception_directory() const
-{
- return directory_exists(image_directory_entry_exception);
-}
-
-//Returns true if image has debug directory
-bool pe_base::has_debug() const
-{
- return directory_exists(image_directory_entry_debug);
-}
-
-//Returns corresponding section data pointer from RVA inside section "s" (checks bounds)
-char* pe_base::section_data_from_rva(section& s, uint32_t rva)
-{
- //Check if RVA is inside section "s"
- if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()))
- {
- if(s.get_raw_data().empty())
- throw pe_exception("Section raw data is empty and cannot be changed", pe_exception::section_is_empty);
-
- return &s.get_raw_data()[rva - s.get_virtual_address()];
- }
-
- throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists);
-}
-
-//Returns corresponding section data pointer from RVA inside section "s" (checks bounds)
-const char* pe_base::section_data_from_rva(const section& s, uint32_t rva, section_data_type datatype) const
-{
- //Check if RVA is inside section "s"
- if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()))
- return (datatype == section_data_raw ? s.get_raw_data().data() : s.get_virtual_data(get_section_alignment()).c_str()) + rva - s.get_virtual_address();
-
- throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists);
-}
-
-//Returns section TOTAL RAW/VIRTUAL data length from RVA inside section
-uint32_t pe_base::section_data_length_from_rva(uint32_t rva, section_data_type datatype, bool include_headers) const
-{
- //if RVA is inside of headers and we're searching them too...
- if(include_headers && rva < full_headers_data_.length())
- return static_cast<unsigned long>(full_headers_data_.length());
-
- const section& s = section_from_rva(rva);
- return static_cast<unsigned long>(datatype == section_data_raw ? s.get_raw_data().length() /* instead of SizeOfRawData */ : s.get_aligned_virtual_size(get_section_alignment()));
-}
-
-//Returns section TOTAL RAW/VIRTUAL data length from VA inside section for PE32
-uint32_t pe_base::section_data_length_from_va(uint32_t va, section_data_type datatype, bool include_headers) const
-{
- return section_data_length_from_rva(va_to_rva(va), datatype, include_headers);
-}
-
-//Returns section TOTAL RAW/VIRTUAL data length from VA inside section for PE32/PE64
-uint32_t pe_base::section_data_length_from_va(uint64_t va, section_data_type datatype, bool include_headers) const
-{
- return section_data_length_from_rva(va_to_rva(va), datatype, include_headers);
-}
-
-//Returns section remaining RAW/VIRTUAL data length from RVA "rva_inside" to the end of section containing RVA "rva"
-uint32_t pe_base::section_data_length_from_rva(uint32_t rva, uint32_t rva_inside, section_data_type datatype, bool include_headers) const
-{
- //if RVAs are inside of headers and we're searching them too...
- if(include_headers && rva < full_headers_data_.length() && rva_inside < full_headers_data_.length())
- return static_cast<unsigned long>(full_headers_data_.length() - rva_inside);
-
- const section& s = section_from_rva(rva);
- if(rva_inside < s.get_virtual_address())
- throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists);
-
- //Calculate remaining length of section data from "rva" address
- long length = static_cast<long>(datatype == section_data_raw ? s.get_raw_data().length() /* instead of SizeOfRawData */ : s.get_aligned_virtual_size(get_section_alignment()))
- + s.get_virtual_address() - rva_inside;
-
- if(length < 0)
- return 0;
-
- return static_cast<unsigned long>(length);
-}
-
-//Returns section remaining RAW/VIRTUAL data length from VA "va_inside" to the end of section containing VA "va" for PE32
-uint32_t pe_base::section_data_length_from_va(uint32_t va, uint32_t va_inside, section_data_type datatype, bool include_headers) const
-{
- return section_data_length_from_rva(va_to_rva(va), va_to_rva(va_inside), datatype, include_headers);
-}
-
-//Returns section remaining RAW/VIRTUAL data length from VA "va_inside" to the end of section containing VA "va" for PE32/PE64
-uint32_t pe_base::section_data_length_from_va(uint64_t va, uint64_t va_inside, section_data_type datatype, bool include_headers) const
-{
- return section_data_length_from_rva(va_to_rva(va), va_to_rva(va_inside), datatype, include_headers);
-}
-
-//Returns section remaining RAW/VIRTUAL data length from RVA to the end of section "s" (checks bounds)
-uint32_t pe_base::section_data_length_from_rva(const section& s, uint32_t rva_inside, section_data_type datatype) const
-{
- //Check rva_inside
- if(rva_inside >= s.get_virtual_address() && rva_inside < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()))
- {
- //Calculate remaining length of section data from "rva" address
- int32_t length = static_cast<int32_t>(datatype == section_data_raw ? s.get_raw_data().length() /* instead of SizeOfRawData */ : s.get_aligned_virtual_size(get_section_alignment()))
- + s.get_virtual_address() - rva_inside;
-
- if(length < 0)
- return 0;
-
- return static_cast<uint32_t>(length);
- }
-
- throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists);
-}
-
-//Returns section remaining RAW/VIRTUAL data length from VA to the end of section "s" for PE32 (checks bounds)
-uint32_t pe_base::section_data_length_from_va(const section& s, uint32_t va_inside, section_data_type datatype) const
-{
- return section_data_length_from_rva(s, va_to_rva(va_inside), datatype);
-}
-
-//Returns section remaining RAW/VIRTUAL data length from VA to the end of section "s" for PE32/PE64 (checks bounds)
-uint32_t pe_base::section_data_length_from_va(const section& s, uint64_t va_inside, section_data_type datatype) const
-{
- return section_data_length_from_rva(s, va_to_rva(va_inside), datatype);
-}
-
-//Returns corresponding section data pointer from RVA inside section
-char* pe_base::section_data_from_rva(uint32_t rva, bool include_headers)
-{
- //if RVA is inside of headers and we're searching them too...
- if(include_headers && rva < full_headers_data_.length())
- return &full_headers_data_[rva];
-
- section& s = section_from_rva(rva);
-
- if(s.get_raw_data().empty())
- throw pe_exception("Section raw data is empty and cannot be changed", pe_exception::section_is_empty);
-
- return &s.get_raw_data()[rva - s.get_virtual_address()];
-}
-
-//Returns corresponding section data pointer from RVA inside section
-const char* pe_base::section_data_from_rva(uint32_t rva, section_data_type datatype, bool include_headers) const
-{
- //if RVA is inside of headers and we're searching them too...
- if(include_headers && rva < full_headers_data_.length())
- return &full_headers_data_[rva];
-
- const section& s = section_from_rva(rva);
- return (datatype == section_data_raw ? s.get_raw_data().data() : s.get_virtual_data(get_section_alignment()).c_str()) + rva - s.get_virtual_address();
-}
-
-//Reads DOS headers from istream
-void pe_base::read_dos_header(std::istream& file, image_dos_header& header)
-{
- //Check istream flags
- if(file.bad() || file.eof())
- throw pe_exception("PE file stream is bad or closed.", pe_exception::bad_pe_file);
-
- //Read DOS header and check istream
- file.read(reinterpret_cast<char*>(&header), sizeof(image_dos_header));
- if(file.bad() || file.eof())
- throw pe_exception("Unable to read IMAGE_DOS_HEADER", pe_exception::bad_dos_header);
-
- //Check DOS header magic
- if(header.e_magic != 0x5a4d) //"MZ"
- throw pe_exception("IMAGE_DOS_HEADER signature is incorrect", pe_exception::bad_dos_header);
-}
-
-//Reads DOS headers from istream
-void pe_base::read_dos_header(std::istream& file)
-{
- read_dos_header(file, dos_header_);
-}
-
-//Reads PE image from istream
-void pe_base::read_pe(std::istream& file, bool read_debug_raw_data)
-{
- //Get istream size
- std::streamoff filesize = pe_utils::get_file_size(file);
-
- //Check if PE header is DWORD-aligned
- if((dos_header_.e_lfanew % sizeof(uint32_t)) != 0)
- throw pe_exception("PE header is not DWORD-aligned", pe_exception::bad_dos_header);
-
- //Seek to NT headers
- file.seekg(dos_header_.e_lfanew);
- if(file.bad() || file.fail())
- throw pe_exception("Cannot reach IMAGE_NT_HEADERS", pe_exception::image_nt_headers_not_found);
-
- //Read NT headers
- file.read(get_nt_headers_ptr(), get_sizeof_nt_header() - sizeof(image_data_directory) * image_numberof_directory_entries);
- if(file.bad() || file.eof())
- throw pe_exception("Error reading IMAGE_NT_HEADERS", pe_exception::error_reading_image_nt_headers);
-
- //Check PE signature
- if(get_pe_signature() != 0x4550) //"PE"
- throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect);
-
- //Check number of directories
- if(get_number_of_rvas_and_sizes() > image_numberof_directory_entries)
- set_number_of_rvas_and_sizes(image_numberof_directory_entries);
-
- if(get_number_of_rvas_and_sizes() > 0)
- {
- //Read data directory headers, if any
- file.read(get_nt_headers_ptr() + (get_sizeof_nt_header() - sizeof(image_data_directory) * image_numberof_directory_entries), sizeof(image_data_directory) * get_number_of_rvas_and_sizes());
- if(file.bad() || file.eof())
- throw pe_exception("Error reading DATA_DIRECTORY headers", pe_exception::error_reading_data_directories);
- }
-
- //Check section number
- //Images with zero section number accepted
- if(get_number_of_sections() > maximum_number_of_sections)
- throw pe_exception("Incorrect number of sections", pe_exception::section_number_incorrect);
-
- //Check PE magic
- if(get_magic() != get_needed_magic())
- throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect);
-
- //Check section alignment
- if(!pe_utils::is_power_of_2(get_section_alignment()))
- throw pe_exception("Incorrect section alignment", pe_exception::incorrect_section_alignment);
-
- //Check file alignment
- if(!pe_utils::is_power_of_2(get_file_alignment()))
- throw pe_exception("Incorrect file alignment", pe_exception::incorrect_file_alignment);
-
- if(get_file_alignment() != get_section_alignment() && (get_file_alignment() < minimum_file_alignment || get_file_alignment() > get_section_alignment()))
- throw pe_exception("Incorrect file alignment", pe_exception::incorrect_file_alignment);
-
- //Check size of image
- if(pe_utils::align_up(get_size_of_image(), get_section_alignment()) == 0)
- throw pe_exception("Incorrect size of image", pe_exception::incorrect_size_of_image);
-
- //Read rich data overlay / DOS stub (if any)
- if(static_cast<uint32_t>(dos_header_.e_lfanew) > sizeof(image_dos_header))
- {
- rich_overlay_.resize(dos_header_.e_lfanew - sizeof(image_dos_header));
- file.seekg(sizeof(image_dos_header));
- file.read(&rich_overlay_[0], dos_header_.e_lfanew - sizeof(image_dos_header));
- if(file.bad() || file.eof())
- throw pe_exception("Error reading 'Rich' & 'DOS stub' overlay", pe_exception::error_reading_overlay);
- }
-
- //Calculate first section raw position
- //Sum is safe here
- uint32_t first_section = dos_header_.e_lfanew + get_size_of_optional_header() + sizeof(image_file_header) + sizeof(uint32_t) /* Signature */;
-
- if(get_number_of_sections() > 0)
- {
- //Go to first section
- file.seekg(first_section);
- if(file.bad() || file.fail())
- throw pe_exception("Cannot reach section headers", pe_exception::image_section_headers_not_found);
- }
-
- uint32_t last_raw_size = 0;
-
- //Read all sections
- for(int i = 0; i < get_number_of_sections(); i++)
- {
- section s;
- //Read section header
- file.read(reinterpret_cast<char*>(&s.get_raw_header()), sizeof(image_section_header));
- if(file.bad() || file.eof())
- throw pe_exception("Error reading section header", pe_exception::error_reading_section_header);
-
- //Save next section header position
- std::streamoff next_sect = file.tellg();
-
- //Check section virtual and raw sizes
- if(!s.get_size_of_raw_data() && !s.get_virtual_size())
- throw pe_exception("Virtual and Physical sizes of section can't be 0 at the same time", pe_exception::zero_section_sizes);
-
- //Check for adequate values of section fields
- if(!pe_utils::is_sum_safe(s.get_virtual_address(), s.get_virtual_size()) || s.get_virtual_size() > pe_utils::two_gb
- || !pe_utils::is_sum_safe(s.get_pointer_to_raw_data(), s.get_size_of_raw_data()) || s.get_size_of_raw_data() > pe_utils::two_gb)
- throw pe_exception("Incorrect section address or size", pe_exception::section_incorrect_addr_or_size);
-
- if(s.get_size_of_raw_data() != 0)
- {
- //If section has raw data
-
- //If section raw data size is greater than virtual, fix it
- last_raw_size = s.get_size_of_raw_data();
- if(pe_utils::align_up(s.get_size_of_raw_data(), get_file_alignment()) > pe_utils::align_up(s.get_virtual_size(), get_section_alignment()))
- s.set_size_of_raw_data(s.get_virtual_size());
-
- //Check virtual and raw section sizes and addresses
- if(s.get_virtual_address() + pe_utils::align_up(s.get_virtual_size(), get_section_alignment()) > pe_utils::align_up(get_size_of_image(), get_section_alignment())
- ||
- pe_utils::align_down(s.get_pointer_to_raw_data(), get_file_alignment()) + s.get_size_of_raw_data() > static_cast<uint32_t>(filesize))
- throw pe_exception("Incorrect section address or size", pe_exception::section_incorrect_addr_or_size);
-
- //Seek to section raw data
- file.seekg(pe_utils::align_down(s.get_pointer_to_raw_data(), get_file_alignment()));
- if(file.bad() || file.fail())
- throw pe_exception("Cannot reach section data", pe_exception::image_section_data_not_found);
-
- //Read section raw data
- s.get_raw_data().resize(s.get_size_of_raw_data());
- file.read(&s.get_raw_data()[0], s.get_size_of_raw_data());
- if(file.bad() || file.fail())
- throw pe_exception("Error reading section data", pe_exception::image_section_data_not_found);
- }
-
- //Check virtual address and size of section
- if(s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()) > pe_utils::align_up(get_size_of_image(), get_section_alignment()))
- throw pe_exception("Incorrect section address or size", pe_exception::section_incorrect_addr_or_size);
-
- //Save section
- sections_.push_back(s);
-
- //Seek to the next section header
- file.seekg(next_sect);
- }
-
- //Check size of headers: SizeOfHeaders can't be larger than first section VA
- if(!sections_.empty() && get_size_of_headers() > sections_.front().get_virtual_address())
- throw pe_exception("Incorrect size of headers", pe_exception::incorrect_size_of_headers);
-
- //If image has more than two sections
- if(sections_.size() >= 2)
- {
- //Check sections virtual sizes
- for(section_list::const_iterator i = sections_.begin() + 1; i != sections_.end(); ++i)
- {
- if((*i).get_virtual_address() != (*(i - 1)).get_virtual_address() + (*(i - 1)).get_aligned_virtual_size(get_section_alignment()))
- throw pe_exception("Section table is incorrect", pe_exception::image_section_table_incorrect);
- }
- }
-
- //Check if image has overlay in the end of file
- has_overlay_ = !sections_.empty() && filesize > static_cast<std::streamoff>(sections_.back().get_pointer_to_raw_data() + last_raw_size);
-
- {
- //Additionally, read data from the beginning of istream to size of headers
- file.seekg(0);
- uint32_t size_of_headers = std::min<uint32_t>(get_size_of_headers(), static_cast<uint32_t>(filesize));
-
- if(!sections_.empty())
- {
- for(section_list::const_iterator i = sections_.begin(); i != sections_.end(); ++i)
- {
- if(!(*i).empty())
- {
- size_of_headers = std::min<uint32_t>(get_size_of_headers(), (*i).get_pointer_to_raw_data());
- break;
- }
- }
- }
-
- full_headers_data_.resize(size_of_headers);
- file.read(&full_headers_data_[0], size_of_headers);
- if(file.bad() || file.eof())
- throw pe_exception("Error reading file", pe_exception::error_reading_file);
- }
-
- //Moreover, if there's debug directory, read its raw data for some debug info types
- while(read_debug_raw_data && has_debug())
- {
- try
- {
- //Check the length in bytes of the section containing debug directory
- if(section_data_length_from_rva(get_directory_rva(image_directory_entry_debug), get_directory_rva(image_directory_entry_debug), section_data_virtual, true) < sizeof(image_debug_directory))
- break;
-
- unsigned long current_pos = get_directory_rva(image_directory_entry_debug);
-
- //First IMAGE_DEBUG_DIRECTORY table
- image_debug_directory directory = section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true);
-
- //Iterate over all IMAGE_DEBUG_DIRECTORY directories
- while(directory.PointerToRawData
- && current_pos < get_directory_rva(image_directory_entry_debug) + get_directory_size(image_directory_entry_debug))
- {
- //If we have something to read
- if((directory.Type == image_debug_type_codeview
- || directory.Type == image_debug_type_misc
- || directory.Type == image_debug_type_coff)
- && directory.SizeOfData)
- {
- std::string data;
- data.resize(directory.SizeOfData);
- file.seekg(directory.PointerToRawData);
- file.read(&data[0], directory.SizeOfData);
- if(file.bad() || file.eof())
- throw pe_exception("Error reading file", pe_exception::error_reading_file);
-
- debug_data_.insert(std::make_pair(directory.PointerToRawData, data));
- }
-
- //Go to next debug entry
- current_pos += sizeof(image_debug_directory);
- directory = section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true);
- }
-
- break;
- }
- catch(const pe_exception&)
- {
- //Don't throw any exception here, if debug info is corrupted or incorrect
- break;
- }
- catch(const std::bad_alloc&)
- {
- //Don't throw any exception here, if debug info is corrupted or incorrect
- break;
- }
- }
-}
-
-//Returns PE type of this image
-pe_type pe_base::get_pe_type() const
-{
- return props_->get_pe_type();
-}
-
-//Returns PE type (PE or PE+) from pe_type enumeration (minimal correctness checks)
-pe_type pe_base::get_pe_type(std::istream& file)
-{
- //Save state of the istream
- std::ios_base::iostate state = file.exceptions();
- std::streamoff old_offset = file.tellg();
- image_nt_headers32 nt_headers;
- image_dos_header header;
-
- try
- {
- //Read dos header
- file.exceptions(std::ios::goodbit);
- read_dos_header(file, header);
-
- //Seek to the NT headers start
- file.seekg(header.e_lfanew);
- if(file.bad() || file.fail())
- throw pe_exception("Cannot reach IMAGE_NT_HEADERS", pe_exception::image_nt_headers_not_found);
-
- //Read NT headers (we're using 32-bit version, because there's no significant differencies between 32 and 64 bit version structures)
- file.read(reinterpret_cast<char*>(&nt_headers), sizeof(image_nt_headers32) - sizeof(image_data_directory) * image_numberof_directory_entries);
- if(file.bad() || file.eof())
- throw pe_exception("Error reading IMAGE_NT_HEADERS", pe_exception::error_reading_image_nt_headers);
-
- //Check NT headers signature
- if(nt_headers.Signature != 0x4550) //"PE"
- throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect);
-
- //Check NT headers magic
- if(nt_headers.OptionalHeader.Magic != image_nt_optional_hdr32_magic && nt_headers.OptionalHeader.Magic != image_nt_optional_hdr64_magic)
- throw pe_exception("Incorrect PE signature", pe_exception::pe_signature_incorrect);
- }
- catch(const std::exception&)
- {
- //If something went wrong, restore istream state
- file.exceptions(state);
- file.seekg(old_offset);
- file.clear();
- //Retrhow exception
- throw;
- }
-
- //Restore stream state
- file.exceptions(state);
- file.seekg(old_offset);
- file.clear();
-
- //Determine PE type and return it
- return nt_headers.OptionalHeader.Magic == image_nt_optional_hdr64_magic ? pe_type_64 : pe_type_32;
-}
-
-//Returns true if image has overlay data at the end of file
-bool pe_base::has_overlay() const
-{
- return has_overlay_;
-}
-
-//Clears PE characteristics flag
-void pe_base::clear_characteristics_flags(uint16_t flags)
-{
- set_characteristics(get_characteristics() & ~flags);
-}
-
-//Sets PE characteristics flag
-void pe_base::set_characteristics_flags(uint16_t flags)
-{
- set_characteristics(get_characteristics() | flags);
-}
-
-//Returns true if PE characteristics flag set
-bool pe_base::check_characteristics_flag(uint16_t flag) const
-{
- return (get_characteristics() & flag) ? true : false;
-}
-
-//Returns subsystem value
-uint16_t pe_base::get_subsystem() const
-{
- return props_->get_subsystem();
-}
-
-//Sets subsystem value
-void pe_base::set_subsystem(uint16_t subsystem)
-{
- props_->set_subsystem(subsystem);
-}
-
-//Returns true if image has console subsystem
-bool pe_base::is_console() const
-{
- return get_subsystem() == image_subsystem_windows_cui;
-}
-
-//Returns true if image has Windows GUI subsystem
-bool pe_base::is_gui() const
-{
- return get_subsystem() == image_subsystem_windows_gui;
-}
-
-//Sets required operation system version
-void pe_base::set_os_version(uint16_t major, uint16_t minor)
-{
- props_->set_os_version(major, minor);
-}
-
-//Returns required operation system version (minor word)
-uint16_t pe_base::get_minor_os_version() const
-{
- return props_->get_minor_os_version();
-}
-
-//Returns required operation system version (major word)
-uint16_t pe_base::get_major_os_version() const
-{
- return props_->get_major_os_version();
-}
-
-//Sets required subsystem version
-void pe_base::set_subsystem_version(uint16_t major, uint16_t minor)
-{
- props_->set_subsystem_version(major, minor);
-}
-
-//Returns required subsystem version (minor word)
-uint16_t pe_base::get_minor_subsystem_version() const
-{
- return props_->get_minor_subsystem_version();
-}
-
-//Returns required subsystem version (major word)
-uint16_t pe_base::get_major_subsystem_version() const
-{
- return props_->get_major_subsystem_version();
-}
-
-//Returns corresponding section data pointer from VA inside section "s" for PE32 (checks bounds)
-char* pe_base::section_data_from_va(section& s, uint32_t va) //Always returns raw data
-{
- return section_data_from_rva(s, va_to_rva(va));
-}
-
-//Returns corresponding section data pointer from VA inside section "s" for PE32 (checks bounds)
-const char* pe_base::section_data_from_va(const section& s, uint32_t va, section_data_type datatype) const
-{
- return section_data_from_rva(s, va_to_rva(va), datatype);
-}
-
-//Returns corresponding section data pointer from VA inside section for PE32
-char* pe_base::section_data_from_va(uint32_t va, bool include_headers) //Always returns raw data
-{
- return section_data_from_rva(va_to_rva(va), include_headers);
-}
-
-//Returns corresponding section data pointer from VA inside section for PE32
-const char* pe_base::section_data_from_va(uint32_t va, section_data_type datatype, bool include_headers) const
-{
- return section_data_from_rva(va_to_rva(va), datatype, include_headers);
-}
-
-//Returns corresponding section data pointer from VA inside section "s" for PE32/PE64 (checks bounds)
-char* pe_base::section_data_from_va(section& s, uint64_t va) //Always returns raw data
-{
- return section_data_from_rva(s, va_to_rva(va));
-}
-
-//Returns corresponding section data pointer from VA inside section "s" for PE32/PE64 (checks bounds)
-const char* pe_base::section_data_from_va(const section& s, uint64_t va, section_data_type datatype) const
-{
- return section_data_from_rva(s, va_to_rva(va), datatype);
-}
-
-//Returns corresponding section data pointer from VA inside section for PE32/PE64
-char* pe_base::section_data_from_va(uint64_t va, bool include_headers) //Always returns raw data
-{
- return section_data_from_rva(va_to_rva(va), include_headers);
-}
-
-//Returns corresponding section data pointer from VA inside section for PE32/PE64
-const char* pe_base::section_data_from_va(uint64_t va, section_data_type datatype, bool include_headers) const
-{
- return section_data_from_rva(va_to_rva(va), datatype, include_headers);
-}
-
-//Returns section from VA inside it for PE32
-section& pe_base::section_from_va(uint32_t va)
-{
- return section_from_rva(va_to_rva(va));
-}
-
-//Returns section from VA inside it for PE32/PE64
-section& pe_base::section_from_va(uint64_t va)
-{
- return section_from_rva(va_to_rva(va));
-}
-
-//Returns section from RVA inside it for PE32
-const section& pe_base::section_from_va(uint32_t va) const
-{
- return section_from_rva(va_to_rva(va));
-}
-
-//Returns section from RVA inside it for PE32/PE64
-const section& pe_base::section_from_va(uint64_t va) const
-{
- return section_from_rva(va_to_rva(va));
-}
-
-uint32_t pe_base::va_to_rva(uint32_t va, bool bound_check) const
-{
- return props_->va_to_rva(va, bound_check);
-}
-
-uint32_t pe_base::va_to_rva(uint64_t va, bool bound_check) const
-{
- return props_->va_to_rva(va, bound_check);
-}
-
-uint32_t pe_base::rva_to_va_32(uint32_t rva) const
-{
- return props_->rva_to_va_32(rva);
-}
-
-uint64_t pe_base::rva_to_va_64(uint32_t rva) const
-{
- return props_->rva_to_va_64(rva);
-}
-
-//Relative Virtual Address (RVA) to Virtual Address (VA) convertion for PE32
-void pe_base::rva_to_va(uint32_t rva, uint32_t& va) const
-{
- va = rva_to_va_32(rva);
-}
-
-//Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32/PE64
-void pe_base::rva_to_va(uint32_t rva, uint64_t& va) const
-{
- va = rva_to_va_64(rva);
-}
-
-//Returns section from file offset (4gb max)
-section& pe_base::section_from_file_offset(uint32_t offset)
-{
- return *file_offset_to_section(offset);
-}
-
-//Returns section from file offset (4gb max)
-const section& pe_base::section_from_file_offset(uint32_t offset) const
-{
- return *file_offset_to_section(offset);
-}
-
-//Returns section and offset (raw data only) from its start from RVA
-const std::pair<uint32_t, const section*> pe_base::section_and_offset_from_rva(uint32_t rva) const
-{
- const section& s = section_from_rva(rva);
- return std::make_pair(rva - s.get_virtual_address(), &s);
-}
-
-//Returns DLL Characteristics
-uint16_t pe_base::get_dll_characteristics() const
-{
- return props_->get_dll_characteristics();
-}
-
-//Sets DLL Characteristics
-void pe_base::set_dll_characteristics(uint16_t characteristics)
-{
- props_->set_dll_characteristics(characteristics);
-}
-
-//Returns size of headers
-uint32_t pe_base::get_size_of_headers() const
-{
- return props_->get_size_of_headers();
-}
-
-//Returns size of optional header
-uint16_t pe_base::get_size_of_optional_header() const
-{
- return props_->get_size_of_optional_header();
-}
-
-//Returns PE signature
-uint32_t pe_base::get_pe_signature() const
-{
- return props_->get_pe_signature();
-}
-
-//Returns magic value
-uint32_t pe_base::get_magic() const
-{
- return props_->get_magic();
-}
-
-//Returns image base for PE32
-void pe_base::get_image_base(uint32_t& base) const
-{
- base = get_image_base_32();
-}
-
-//Returns image base for PE32 and PE64 respectively
-uint32_t pe_base::get_image_base_32() const
-{
- return props_->get_image_base_32();
-}
-
-//Sets image base for PE32 and PE64 respectively
-uint64_t pe_base::get_image_base_64() const
-{
- return props_->get_image_base_64();
-}
-
-//RVA to RAW file offset convertion (4gb max)
-uint32_t pe_base::rva_to_file_offset(uint32_t rva) const
-{
- //Maybe, RVA is inside PE headers
- if(rva < get_size_of_headers())
- return rva;
-
- const section& s = section_from_rva(rva);
- return s.get_pointer_to_raw_data() + rva - s.get_virtual_address();
-}
-
-//RAW file offset to RVA convertion (4gb max)
-uint32_t pe_base::file_offset_to_rva(uint32_t offset) const
-{
- //Maybe, offset is inside PE headers
- if(offset < get_size_of_headers())
- return offset;
-
- const section_list::const_iterator it = file_offset_to_section(offset);
- return offset - (*it).get_pointer_to_raw_data() + (*it).get_virtual_address();
-}
-
-//RAW file offset to section convertion helper (4gb max)
-section_list::const_iterator pe_base::file_offset_to_section(uint32_t offset) const
-{
- section_list::const_iterator it = std::find_if(sections_.begin(), sections_.end(), section_by_raw_offset(offset));
- if(it == sections_.end())
- throw pe_exception("No section found by presented file offset", pe_exception::no_section_found);
-
- return it;
-}
-
-//RAW file offset to section convertion helper (4gb max)
-section_list::iterator pe_base::file_offset_to_section(uint32_t offset)
-{
- section_list::iterator it = std::find_if(sections_.begin(), sections_.end(), section_by_raw_offset(offset));
- if(it == sections_.end())
- throw pe_exception("No section found by presented file offset", pe_exception::no_section_found);
-
- return it;
-}
-
-//RVA from section raw data offset
-uint32_t pe_base::rva_from_section_offset(const section& s, uint32_t raw_offset_from_section_start)
-{
- return s.get_virtual_address() + raw_offset_from_section_start;
-}
-
-//Returns image base for PE32/PE64
-void pe_base::get_image_base(uint64_t& base) const
-{
- base = get_image_base_64();
-}
-
-//Sets new image base
-void pe_base::set_image_base(uint32_t base)
-{
- props_->set_image_base(base);
-}
-
-void pe_base::set_image_base_64(uint64_t base)
-{
- props_->set_image_base_64(base);
-}
-
-//Sets heap size commit for PE32 and PE64 respectively
-void pe_base::set_heap_size_commit(uint32_t size)
-{
- props_->set_heap_size_commit(size);
-}
-
-void pe_base::set_heap_size_commit(uint64_t size)
-{
- props_->set_heap_size_commit(size);
-}
-
-//Sets heap size reserve for PE32 and PE64 respectively
-void pe_base::set_heap_size_reserve(uint32_t size)
-{
- props_->set_heap_size_reserve(size);
-}
-
-void pe_base::set_heap_size_reserve(uint64_t size)
-{
- props_->set_heap_size_reserve(size);
-}
-
-//Sets stack size commit for PE32 and PE64 respectively
-void pe_base::set_stack_size_commit(uint32_t size)
-{
- props_->set_stack_size_commit(size);
-}
-
-void pe_base::set_stack_size_commit(uint64_t size)
-{
- props_->set_stack_size_commit(size);
-}
-
-//Sets stack size reserve for PE32 and PE64 respectively
-void pe_base::set_stack_size_reserve(uint32_t size)
-{
- props_->set_stack_size_reserve(size);
-}
-
-void pe_base::set_stack_size_reserve(uint64_t size)
-{
- props_->set_stack_size_reserve(size);
-}
-
-//Returns heap size commit for PE32 and PE64 respectively
-uint32_t pe_base::get_heap_size_commit_32() const
-{
- return props_->get_heap_size_commit_32();
-}
-
-uint64_t pe_base::get_heap_size_commit_64() const
-{
- return props_->get_heap_size_commit_64();
-}
-
-//Returns heap size reserve for PE32 and PE64 respectively
-uint32_t pe_base::get_heap_size_reserve_32() const
-{
- return props_->get_heap_size_reserve_32();
-}
-
-uint64_t pe_base::get_heap_size_reserve_64() const
-{
- return props_->get_heap_size_reserve_64();
-}
-
-//Returns stack size commit for PE32 and PE64 respectively
-uint32_t pe_base::get_stack_size_commit_32() const
-{
- return props_->get_stack_size_commit_32();
-}
-
-uint64_t pe_base::get_stack_size_commit_64() const
-{
- return props_->get_stack_size_commit_64();
-}
-
-//Returns stack size reserve for PE32 and PE64 respectively
-uint32_t pe_base::get_stack_size_reserve_32() const
-{
- return props_->get_stack_size_reserve_32();
-}
-
-uint64_t pe_base::get_stack_size_reserve_64() const
-{
- return props_->get_stack_size_reserve_64();
-}
-
-//Returns heap size commit for PE32
-void pe_base::get_heap_size_commit(uint32_t& size) const
-{
- size = get_heap_size_commit_32();
-}
-
-//Returns heap size commit for PE32/PE64
-void pe_base::get_heap_size_commit(uint64_t& size) const
-{
- size = get_heap_size_commit_64();
-}
-
-//Returns heap size reserve for PE32
-void pe_base::get_heap_size_reserve(uint32_t& size) const
-{
- size = get_heap_size_reserve_32();
-}
-
-//Returns heap size reserve for PE32/PE64
-void pe_base::get_heap_size_reserve(uint64_t& size) const
-{
- size = get_heap_size_reserve_64();
-}
-
-//Returns stack size commit for PE32
-void pe_base::get_stack_size_commit(uint32_t& size) const
-{
- size = get_stack_size_commit_32();
-}
-
-//Returns stack size commit for PE32/PE64
-void pe_base::get_stack_size_commit(uint64_t& size) const
-{
- size = get_stack_size_commit_64();
-}
-
-//Returns stack size reserve for PE32
-void pe_base::get_stack_size_reserve(uint32_t& size) const
-{
- size = get_stack_size_reserve_32();
-}
-
-//Returns stack size reserve for PE32/PE64
-void pe_base::get_stack_size_reserve(uint64_t& size) const
-{
- size = get_stack_size_reserve_64();
-}
-
-//Realigns file (changes file alignment)
-void pe_base::realign_file(uint32_t new_file_alignment)
-{
- //Checks alignment for correctness
- set_file_alignment(new_file_alignment);
- realign_all_sections();
-}
-
-//Helper function to recalculate RAW and virtual section sizes and strip it, if necessary
-void pe_base::recalculate_section_sizes(section& s, bool auto_strip)
-{
- prepare_section(s); //Recalculate section raw addresses
-
- //Strip RAW size of section, if it is the last one
- //For all others it must be file-aligned and calculated by prepare_section() call
- if(auto_strip && !(sections_.empty() || &s == &*(sections_.end() - 1)))
- {
- //Strip ending raw data nullbytes to optimize size
- std::string& raw_data = s.get_raw_data();
- if(!raw_data.empty())
- {
- std::string::size_type i = raw_data.length();
- for(; i != 1; --i)
- {
- if(raw_data[i - 1] != 0)
- break;
- }
-
- raw_data.resize(i);
- }
-
- s.set_size_of_raw_data(static_cast<uint32_t>(raw_data.length()));
- }
-
- //Can occur only for last section
- if(pe_utils::align_up(s.get_virtual_size(), get_section_alignment()) < pe_utils::align_up(s.get_size_of_raw_data(), get_file_alignment()))
- set_section_virtual_size(s, pe_utils::align_up(s.get_size_of_raw_data(), get_section_alignment())); //Recalculate section virtual size
-}
-
-//Returns data from the beginning of image
-//Size = SizeOfHeaders
-const std::string& pe_base::get_full_headers_data() const
-{
- return full_headers_data_;
-}
-
-const pe_base::debug_data_list& pe_base::get_raw_debug_data_list() const
-{
- return debug_data_;
-}
-
-//Sets number of sections
-void pe_base::set_number_of_sections(uint16_t number)
-{
- props_->set_number_of_sections(number);
-}
-
-//Sets size of image
-void pe_base::set_size_of_image(uint32_t size)
-{
- props_->set_size_of_image(size);
-}
-
-//Sets size of headers
-void pe_base::set_size_of_headers(uint32_t size)
-{
- props_->set_size_of_headers(size);
-}
-
-//Sets size of optional headers
-void pe_base::set_size_of_optional_header(uint16_t size)
-{
- props_->set_size_of_optional_header(size);
-}
-
-//Returns nt headers data pointer
-char* pe_base::get_nt_headers_ptr()
-{
- return props_->get_nt_headers_ptr();
-}
-
-//Returns nt headers data pointer
-const char* pe_base::get_nt_headers_ptr() const
-{
- return props_->get_nt_headers_ptr();
-}
-
-//Returns sizeof() nt headers
-uint32_t pe_base::get_sizeof_nt_header() const
-{
- return props_->get_sizeof_nt_header();
-}
-
-//Returns sizeof() optional headers
-uint32_t pe_base::get_sizeof_opt_headers() const
-{
- return props_->get_sizeof_opt_headers();
-}
-
-//Sets file alignment (no checks)
-void pe_base::set_file_alignment_unchecked(uint32_t alignment)
-{
- props_->set_file_alignment_unchecked(alignment);
-}
-
-//Sets base of code
-void pe_base::set_base_of_code(uint32_t base)
-{
- props_->set_base_of_code(base);
-}
-
-//Returns base of code
-uint32_t pe_base::get_base_of_code() const
-{
- return props_->get_base_of_code();
-}
-
-//Returns needed magic of image
-uint32_t pe_base::get_needed_magic() const
-{
- return props_->get_needed_magic();
-}
-}
diff --git a/tools/pe_bliss/pe_base.h b/tools/pe_bliss/pe_base.h
deleted file mode 100644
index b5416cf1e2..0000000000
--- a/tools/pe_bliss/pe_base.h
+++ /dev/null
@@ -1,544 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include <vector>
-#include <istream>
-#include <ostream>
-#include <map>
-#include "pe_exception.h"
-#include "pe_structures.h"
-#include "utils.h"
-#include "pe_section.h"
-#include "pe_properties.h"
-
-//Please don't remove this information from header
-//PEBliss 1.0.0
-//(c) DX 2011 - 2012, http://kaimi.ru
-//Free to use for commertial and non-commertial purposes, modification and distribution
-
-// == more important ==
-//TODO: compact import rebuilder
-//TODO: remove sections in the middle
-//== less important ==
-//TODO: relocations that take more than one element (seems to be not possible in Windows PE, but anyway)
-//TODO: delay import directory
-//TODO: write message tables
-//TODO: write string tables
-//TODO: read security information
-//TODO: read full .NET information
-
-namespace pe_bliss
-{
-//Portable executable class
-class pe_base
-{
-public: //CONSTRUCTORS
- //Constructor from stream
- pe_base(std::istream& file, const pe_properties& props, bool read_debug_raw_data = true);
-
- //Constructor of empty PE-file
- explicit pe_base(const pe_properties& props, uint32_t section_alignment = 0x1000, bool dll = false, uint16_t subsystem = pe_win::image_subsystem_windows_gui);
-
- pe_base(const pe_base& pe);
- pe_base& operator=(const pe_base& pe);
-
-public:
- ~pe_base();
-
-public: //STUB
- //Strips stub MSVS overlay, if any
- void strip_stub_overlay();
- //Fills stub MSVS overlay with specified byte
- void fill_stub_overlay(char c);
- //Sets stub MSVS overlay
- void set_stub_overlay(const std::string& data);
- //Returns stub overlay contents
- const std::string& get_stub_overlay() const;
-
-
-public: //DIRECTORIES
- //Returns true if directory exists
- bool directory_exists(uint32_t id) const;
- //Removes directory
- void remove_directory(uint32_t id);
-
- //Returns directory RVA
- uint32_t get_directory_rva(uint32_t id) const;
- //Returns directory size
- uint32_t get_directory_size(uint32_t id) const;
-
- //Sets directory RVA (just a value of PE header, no moving occurs)
- void set_directory_rva(uint32_t id, uint32_t rva);
- //Sets directory size (just a value of PE header, no moving occurs)
- void set_directory_size(uint32_t id, uint32_t size);
-
- //Strips only zero DATA_DIRECTORY entries to count = min_count
- //Returns resulting number of data directories
- //strip_iat_directory - if true, even not empty IAT directory will be stripped
- uint32_t strip_data_directories(uint32_t min_count = 1, bool strip_iat_directory = true);
-
- //Returns true if image has import directory
- bool has_imports() const;
- //Returns true if image has export directory
- bool has_exports() const;
- //Returns true if image has resource directory
- bool has_resources() const;
- //Returns true if image has security directory
- bool has_security() const;
- //Returns true if image has relocations
- bool has_reloc() const;
- //Returns true if image has TLS directory
- bool has_tls() const;
- //Returns true if image has config directory
- bool has_config() const;
- //Returns true if image has bound import directory
- bool has_bound_import() const;
- //Returns true if image has delay import directory
- bool has_delay_import() const;
- //Returns true if image has COM directory
- bool is_dotnet() const;
- //Returns true if image has exception directory
- bool has_exception_directory() const;
- //Returns true if image has debug directory
- bool has_debug() const;
-
- //Returns subsystem value
- uint16_t get_subsystem() const;
- //Sets subsystem value
- void set_subsystem(uint16_t subsystem);
- //Returns true if image has console subsystem
- bool is_console() const;
- //Returns true if image has Windows GUI subsystem
- bool is_gui() const;
-
- //Sets required operation system version
- void set_os_version(uint16_t major, uint16_t minor);
- //Returns required operation system version (minor word)
- uint16_t get_minor_os_version() const;
- //Returns required operation system version (major word)
- uint16_t get_major_os_version() const;
-
- //Sets required subsystem version
- void set_subsystem_version(uint16_t major, uint16_t minor);
- //Returns required subsystem version (minor word)
- uint16_t get_minor_subsystem_version() const;
- //Returns required subsystem version (major word)
- uint16_t get_major_subsystem_version() const;
-
-public: //PE HEADER
- //Returns DOS header
- const pe_win::image_dos_header& get_dos_header() const;
- pe_win::image_dos_header& get_dos_header();
-
- //Returns PE header start (e_lfanew)
- int32_t get_pe_header_start() const;
-
- //Returns file alignment
- uint32_t get_file_alignment() const;
- //Sets file alignment, checking the correctness of its value
- void set_file_alignment(uint32_t alignment);
-
- //Returns size of image
- uint32_t get_size_of_image() const;
-
- //Returns image entry point
- uint32_t get_ep() const;
- //Sets image entry point (just a value of PE header)
- void set_ep(uint32_t new_ep);
-
- //Returns number of RVA and sizes (number of DATA_DIRECTORY entries)
- uint32_t get_number_of_rvas_and_sizes() const;
- //Sets number of RVA and sizes (number of DATA_DIRECTORY entries)
- void set_number_of_rvas_and_sizes(uint32_t number);
-
- //Returns PE characteristics
- uint16_t get_characteristics() const;
- //Sets PE characteristics (a value inside header)
- void set_characteristics(uint16_t ch);
- //Clears PE characteristics flag
- void clear_characteristics_flags(uint16_t flags);
- //Sets PE characteristics flag
- void set_characteristics_flags(uint16_t flags);
- //Returns true if PE characteristics flag set
- bool check_characteristics_flag(uint16_t flag) const;
-
- //Returns DLL Characteristics
- uint16_t get_dll_characteristics() const;
- //Sets DLL Characteristics
- void set_dll_characteristics(uint16_t characteristics);
-
- //Returns size of headers
- uint32_t get_size_of_headers() const;
- //Returns size of optional header
- uint16_t get_size_of_optional_header() const;
-
- //Returns PE signature
- uint32_t get_pe_signature() const;
-
- //Returns magic value
- uint32_t get_magic() const;
-
- //Returns image base for PE32 and PE64 respectively
- uint32_t get_image_base_32() const;
- void get_image_base(uint32_t& base) const;
- //Sets image base for PE32 and PE64 respectively
- uint64_t get_image_base_64() const;
- void get_image_base(uint64_t& base) const;
-
- //Sets new image base
- void set_image_base(uint32_t base);
- void set_image_base_64(uint64_t base);
-
- //Sets heap size commit for PE32 and PE64 respectively
- void set_heap_size_commit(uint32_t size);
- void set_heap_size_commit(uint64_t size);
- //Sets heap size reserve for PE32 and PE64 respectively
- void set_heap_size_reserve(uint32_t size);
- void set_heap_size_reserve(uint64_t size);
- //Sets stack size commit for PE32 and PE64 respectively
- void set_stack_size_commit(uint32_t size);
- void set_stack_size_commit(uint64_t size);
- //Sets stack size reserve for PE32 and PE64 respectively
- void set_stack_size_reserve(uint32_t size);
- void set_stack_size_reserve(uint64_t size);
-
- //Returns heap size commit for PE32 and PE64 respectively
- uint32_t get_heap_size_commit_32() const;
- void get_heap_size_commit(uint32_t& size) const;
- uint64_t get_heap_size_commit_64() const;
- void get_heap_size_commit(uint64_t& size) const;
- //Returns heap size reserve for PE32 and PE64 respectively
- uint32_t get_heap_size_reserve_32() const;
- void get_heap_size_reserve(uint32_t& size) const;
- uint64_t get_heap_size_reserve_64() const;
- void get_heap_size_reserve(uint64_t& size) const;
- //Returns stack size commit for PE32 and PE64 respectively
- uint32_t get_stack_size_commit_32() const;
- void get_stack_size_commit(uint32_t& size) const;
- uint64_t get_stack_size_commit_64() const;
- void get_stack_size_commit(uint64_t& size) const;
- //Returns stack size reserve for PE32 and PE64 respectively
- uint32_t get_stack_size_reserve_32() const;
- void get_stack_size_reserve(uint32_t& size) const;
- uint64_t get_stack_size_reserve_64() const;
- void get_stack_size_reserve(uint64_t& size) const;
-
- //Updates virtual size of image corresponding to section virtual sizes
- void update_image_size();
-
- //Returns checksum of PE file from header
- uint32_t get_checksum() const;
- //Sets checksum of PE file
- void set_checksum(uint32_t checksum);
-
- //Returns timestamp of PE file from header
- uint32_t get_time_date_stamp() const;
- //Sets timestamp of PE file
- void set_time_date_stamp(uint32_t timestamp);
-
- //Returns Machine field value of PE file from header
- uint16_t get_machine() const;
- //Sets Machine field value of PE file
- void set_machine(uint16_t machine);
-
- //Returns data from the beginning of image
- //Size = SizeOfHeaders
- const std::string& get_full_headers_data() const;
-
- typedef std::multimap<uint32_t, std::string> debug_data_list;
- //Returns raw list of debug data
- const debug_data_list& get_raw_debug_data_list() const;
-
- //Reads and checks DOS header
- static void read_dos_header(std::istream& file, pe_win::image_dos_header& header);
-
- //Returns sizeof() nt headers
- uint32_t get_sizeof_nt_header() const;
- //Returns sizeof() optional headers
- uint32_t get_sizeof_opt_headers() const;
- //Returns raw nt headers data pointer
- const char* get_nt_headers_ptr() const;
-
- //Sets size of headers (to NT headers)
- void set_size_of_headers(uint32_t size);
- //Sets size of optional headers (to NT headers)
- void set_size_of_optional_header(uint16_t size);
-
- //Sets base of code
- void set_base_of_code(uint32_t base);
- //Returns base of code
- uint32_t get_base_of_code() const;
-
-public: //ADDRESS CONVERTIONS
- //Virtual Address (VA) to Relative Virtual Address (RVA) convertions
- //for PE32 and PE64 respectively
- //bound_check checks integer overflow
- uint32_t va_to_rva(uint32_t va, bool bound_check = true) const;
- uint32_t va_to_rva(uint64_t va, bool bound_check = true) const;
-
- //Relative Virtual Address (RVA) to Virtual Address (VA) convertions
- //for PE32 and PE64 respectively
- uint32_t rva_to_va_32(uint32_t rva) const;
- void rva_to_va(uint32_t rva, uint32_t& va) const;
- uint64_t rva_to_va_64(uint32_t rva) const;
- void rva_to_va(uint32_t rva, uint64_t& va) const;
-
- //RVA to RAW file offset convertion (4gb max)
- uint32_t rva_to_file_offset(uint32_t rva) const;
- //RAW file offset to RVA convertion (4gb max)
- uint32_t file_offset_to_rva(uint32_t offset) const;
-
- //RVA from section raw data offset
- static uint32_t rva_from_section_offset(const section& s, uint32_t raw_offset_from_section_start);
-
-public: //IMAGE SECTIONS
- //Returns number of sections from PE header
- uint16_t get_number_of_sections() const;
-
- //Updates number of sections in PE header
- uint16_t update_number_of_sections();
-
- //Returns section alignment
- uint32_t get_section_alignment() const;
-
- //Returns section list
- section_list& get_image_sections();
- const section_list& get_image_sections() const;
-
- //Realigns all sections, if you made any changes to sections or alignments
- void realign_all_sections();
- //Resligns section with specified index
- void realign_section(uint32_t index);
-
- //Returns section from RVA inside it
- section& section_from_rva(uint32_t rva);
- const section& section_from_rva(uint32_t rva) const;
- //Returns section from directory ID
- section& section_from_directory(uint32_t directory_id);
- const section& section_from_directory(uint32_t directory_id) const;
- //Returns section from VA inside it for PE32 and PE64 respectively
- section& section_from_va(uint32_t va);
- const section& section_from_va(uint32_t va) const;
- section& section_from_va(uint64_t va);
- const section& section_from_va(uint64_t va) const;
- //Returns section from file offset (4gb max)
- section& section_from_file_offset(uint32_t offset);
- const section& section_from_file_offset(uint32_t offset) const;
-
- //Returns section TOTAL RAW/VIRTUAL data length from RVA inside section
- //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too
- uint32_t section_data_length_from_rva(uint32_t rva, section_data_type datatype = section_data_raw, bool include_headers = false) const;
- //Returns section TOTAL RAW/VIRTUAL data length from VA inside section for PE32 and PE64 respectively
- //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too
- uint32_t section_data_length_from_va(uint32_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const;
- uint32_t section_data_length_from_va(uint64_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const;
-
- //Returns section remaining RAW/VIRTUAL data length from RVA to the end of section "s" (checks bounds)
- uint32_t section_data_length_from_rva(const section& s, uint32_t rva_inside, section_data_type datatype = section_data_raw) const;
- //Returns section remaining RAW/VIRTUAL data length from VA to the end of section "s" for PE32 and PE64 respectively (checks bounds)
- uint32_t section_data_length_from_va(const section& s, uint64_t va_inside, section_data_type datatype = section_data_raw) const;
- uint32_t section_data_length_from_va(const section& s, uint32_t va_inside, section_data_type datatype = section_data_raw) const;
-
- //Returns section remaining RAW/VIRTUAL data length from RVA "rva_inside" to the end of section containing RVA "rva"
- //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too
- uint32_t section_data_length_from_rva(uint32_t rva, uint32_t rva_inside, section_data_type datatype = section_data_raw, bool include_headers = false) const;
- //Returns section remaining RAW/VIRTUAL data length from VA "va_inside" to the end of section containing VA "va" for PE32 and PE64 respectively
- //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too
- uint32_t section_data_length_from_va(uint32_t va, uint32_t va_inside, section_data_type datatype = section_data_raw, bool include_headers = false) const;
- uint32_t section_data_length_from_va(uint64_t va, uint64_t va_inside, section_data_type datatype = section_data_raw, bool include_headers = false) const;
-
- //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too
- //Returns corresponding section data pointer from RVA inside section
- char* section_data_from_rva(uint32_t rva, bool include_headers = false);
- const char* section_data_from_rva(uint32_t rva, section_data_type datatype = section_data_raw, bool include_headers = false) const;
- //Returns corresponding section data pointer from VA inside section for PE32 and PE64 respectively
- char* section_data_from_va(uint32_t va, bool include_headers = false);
- const char* section_data_from_va(uint32_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const;
- char* section_data_from_va(uint64_t va, bool include_headers = false);
- const char* section_data_from_va(uint64_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const;
-
- //Returns corresponding section data pointer from RVA inside section "s" (checks bounds)
- char* section_data_from_rva(section& s, uint32_t rva);
- const char* section_data_from_rva(const section& s, uint32_t rva, section_data_type datatype = section_data_raw) const;
- //Returns corresponding section data pointer from VA inside section "s" for PE32 and PE64 respectively (checks bounds)
- char* section_data_from_va(section& s, uint32_t va); //Always returns raw data
- const char* section_data_from_va(const section& s, uint32_t va, section_data_type datatype = section_data_raw) const;
- char* section_data_from_va(section& s, uint64_t va); //Always returns raw data
- const char* section_data_from_va(const section& s, uint64_t va, section_data_type datatype = section_data_raw) const;
-
- //Returns corresponding section data pointer from RVA inside section "s" (checks bounds, checks sizes, the most safe function)
- template<typename T>
- T section_data_from_rva(const section& s, uint32_t rva, section_data_type datatype = section_data_raw) const
- {
- if(rva >= s.get_virtual_address() && rva < s.get_virtual_address() + s.get_aligned_virtual_size(get_section_alignment()) && pe_utils::is_sum_safe(rva, sizeof(T)))
- {
- const std::string& data = datatype == section_data_raw ? s.get_raw_data() : s.get_virtual_data(get_section_alignment());
- //Don't check for underflow here, comparsion is unsigned
- if(data.size() < rva - s.get_virtual_address() + sizeof(T))
- throw pe_exception("RVA and requested data size does not exist inside section", pe_exception::rva_not_exists);
-
- return *reinterpret_cast<const T*>(data.data() + rva - s.get_virtual_address());
- }
-
- throw pe_exception("RVA not found inside section", pe_exception::rva_not_exists);
- }
-
- //Returns corresponding section data pointer from RVA inside section (checks rva, checks sizes, the most safe function)
- //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too
- template<typename T>
- T section_data_from_rva(uint32_t rva, section_data_type datatype = section_data_raw, bool include_headers = false) const
- {
- //if RVA is inside of headers and we're searching them too...
- if(include_headers && pe_utils::is_sum_safe(rva, sizeof(T)) && (rva + sizeof(T) < full_headers_data_.length()))
- return *reinterpret_cast<const T*>(&full_headers_data_[rva]);
-
- const section& s = section_from_rva(rva);
- const std::string& data = datatype == section_data_raw ? s.get_raw_data() : s.get_virtual_data(get_section_alignment());
- //Don't check for underflow here, comparsion is unsigned
- if(data.size() < rva - s.get_virtual_address() + sizeof(T))
- throw pe_exception("RVA and requested data size does not exist inside section", pe_exception::rva_not_exists);
-
- return *reinterpret_cast<const T*>(data.data() + rva - s.get_virtual_address());
- }
-
- //Returns corresponding section data pointer from VA inside section "s" (checks bounds, checks sizes, the most safe function)
- template<typename T>
- T section_data_from_va(const section& s, uint32_t va, section_data_type datatype = section_data_raw) const
- {
- return section_data_from_rva<T>(s, va_to_rva(va), datatype);
- }
-
- template<typename T>
- T section_data_from_va(const section& s, uint64_t va, section_data_type datatype = section_data_raw) const
- {
- return section_data_from_rva<T>(s, va_to_rva(va), datatype);
- }
-
- //Returns corresponding section data pointer from VA inside section (checks rva, checks sizes, the most safe function)
- //If include_headers = true, data from the beginning of PE file to SizeOfHeaders will be searched, too
- template<typename T>
- T section_data_from_va(uint32_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const
- {
- return section_data_from_rva<T>(va_to_rva(va), datatype, include_headers);
- }
-
- template<typename T>
- T section_data_from_va(uint64_t va, section_data_type datatype = section_data_raw, bool include_headers = false) const
- {
- return section_data_from_rva<T>(va_to_rva(va), datatype, include_headers);
- }
-
- //Returns section and offset (raw data only) from its start from RVA
- const std::pair<uint32_t, const section*> section_and_offset_from_rva(uint32_t rva) const;
-
- //Sets virtual size of section "s"
- //Section must be free (not bound to any image)
- //or the last section of this image
- //Function calls update_image_size automatically in second case
- void set_section_virtual_size(section& s, uint32_t vsize);
-
- //Represents section expand type for expand_section function
- enum section_expand_type
- {
- expand_section_raw, //Section raw data size will be expanded
- expand_section_virtual //Section virtual data size will be expanded
- };
-
- //Expands section raw or virtual size to hold data from specified RVA with specified size
- //Section must be free (not bound to any image)
- //or the last section of this image
- //Returns true if section was expanded
- bool expand_section(section& s, uint32_t needed_rva, uint32_t needed_size, section_expand_type expand);
-
- //Adds section to image
- //Returns last section
- section& add_section(section s);
- //Prepares section to later add it to image (checks and recalculates virtual and raw section size)
- //Section must be prepared by this function before calling add_section
- void prepare_section(section& s);
-
- //Returns true if sectios "s" is already attached to this PE file
- bool section_attached(const section& s) const;
-
-
-public: //IMAGE
- //Returns PE type (PE or PE+) from pe_type enumeration (minimal correctness checks)
- static pe_type get_pe_type(std::istream& file);
- //Returns PE type of this image
- pe_type get_pe_type() const;
-
- //Returns true if image has overlay data at the end of file
- bool has_overlay() const;
-
- //Realigns file (changes file alignment)
- void realign_file(uint32_t new_file_alignment);
-
- //Helper function to recalculate RAW and virtual section sizes and strip it, if necessary
- //auto_strip = strip section, if necessary
- void recalculate_section_sizes(section& s, bool auto_strip);
-
- // ========== END OF PUBLIC MEMBERS AND STRUCTURES ========== //
-private:
- //Image DOS header
- pe_win::image_dos_header dos_header_;
- //Rich (stub) overlay data (for MSVS)
- std::string rich_overlay_;
- //List of image sections
- section_list sections_;
- //True if image has overlay
- bool has_overlay_;
- //Raw SizeOfHeaders-sized data from the beginning of image
- std::string full_headers_data_;
- //Raw debug data for all directories
- //PointerToRawData; Data
- debug_data_list debug_data_;
- //PE or PE+ related properties
- pe_properties* props_;
-
- //Reads and checks DOS header
- void read_dos_header(std::istream& file);
-
- //Reads and checks PE headers and section headers, data
- void read_pe(std::istream& file, bool read_debug_raw_data);
-
- //Sets number of sections
- void set_number_of_sections(uint16_t number);
- //Sets size of image
- void set_size_of_image(uint32_t size);
- //Sets file alignment (no checks)
- void set_file_alignment_unchecked(uint32_t alignment);
- //Returns needed magic of image
- uint32_t get_needed_magic() const;
- //Returns nt headers data pointer
- char* get_nt_headers_ptr();
-
-private:
- static const uint16_t maximum_number_of_sections = 0x60;
- static const uint32_t minimum_file_alignment = 512;
-
-private:
- //RAW file offset to section convertion helpers (4gb max)
- section_list::const_iterator file_offset_to_section(uint32_t offset) const;
- section_list::iterator file_offset_to_section(uint32_t offset);
-};
-}
diff --git a/tools/pe_bliss/pe_bliss.h b/tools/pe_bliss/pe_bliss.h
deleted file mode 100644
index 1a8b430284..0000000000
--- a/tools/pe_bliss/pe_bliss.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include "pe_base.h"
-#include "pe_rebuilder.h"
-#include "pe_factory.h"
-#include "pe_bound_import.h"
-#include "pe_debug.h"
-#include "pe_dotnet.h"
-#include "pe_exception_directory.h"
-#include "pe_exports.h"
-#include "pe_imports.h"
-#include "pe_load_config.h"
-#include "pe_relocations.h"
-#include "pe_resources.h"
-#include "pe_rich_data.h"
-#include "pe_tls.h"
-#include "pe_properties_generic.h"
-#include "pe_checksum.h"
-#include "entropy.h"
diff --git a/tools/pe_bliss/pe_bliss_godot.cpp b/tools/pe_bliss/pe_bliss_godot.cpp
deleted file mode 100644
index 8297aa1045..0000000000
--- a/tools/pe_bliss/pe_bliss_godot.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "pe_bliss/pe_bliss.h"
-#include "pe_bliss/pe_bliss_resources.h"
-#include "core/ustring.h"
-#include "core/dvector.h"
-#include "os/file_access.h"
-
-using namespace pe_bliss;
-
-String pe_bliss_add_resrc(const char* p_path, int version_major, int version_minor,
- String& company_name, String& file_description,
- String& legal_copyright, String& version_text,
- String& product_name, String& godot_version,
- DVector<uint8_t>& icon_content) {
- try
- {
- pe_base image(pe_factory::create_pe(p_path));
-
- const section_list& pe_sections = image.get_image_sections();
- uint32_t end_of_pe = 0;
- FileAccess *dst;
- DVector<uint8_t> overlay_data;
- if(image.has_overlay())
- {
- end_of_pe = pe_sections.back().get_pointer_to_raw_data() + pe_sections.back().get_size_of_raw_data();
- dst=FileAccess::open(p_path,FileAccess::READ);
- if (dst) {
- overlay_data.resize(dst->get_len()-end_of_pe);
- dst->seek(end_of_pe);
- DVector<uint8_t>::Write overlay_data_write = overlay_data.write();
- dst->get_buffer(overlay_data_write.ptr(),overlay_data.size());
- dst->close();
- memdelete(dst);
- }
- }
- resource_directory root;
- if(image.has_resources())
- {
- root = resource_directory(get_resources(image));
- }
- pe_resource_manager res(root);
- if(image.has_resources())
- {
- if(icon_content.size()) {
- if(res.resource_exists(pe_resource_viewer::resource_icon))
- {
- res.remove_resource_type(pe_resource_viewer::resource_icon);
- }
- if(res.resource_exists(pe_resource_viewer::resource_icon_group))
- {
- res.remove_resource_type(pe_resource_viewer::resource_icon_group);
- }
- }
- if(res.resource_exists(pe_resource_viewer::resource_version))
- {
- res.remove_resource_type(pe_resource_viewer::resource_version);
- }
- }
- file_version_info file_info;
- file_info.set_file_os(file_version_info::file_os_nt_win32);
- file_info.set_file_type(file_version_info::file_type_application);
- unsigned int ver = version_major << 16;
- ver = ver + version_minor;
- file_info.set_file_version_ms(ver);
- file_info.set_file_version_ls(0x00000000);
- file_info.set_product_version_ms(ver);
- file_info.set_product_version_ls(0x00000000);
- lang_string_values_map strings;
- translation_values_map translations;
- version_info_editor version(strings, translations);
- version.add_translation(version_info_editor::default_language_translation);
- version.set_company_name(company_name.c_str());
- version.set_file_description(file_description.c_str());
- if (!product_name.empty()) {
- version.set_internal_name((product_name+String(".exe")).c_str());
- version.set_original_filename((product_name+String(".exe")).c_str());
- version.set_product_name(product_name.c_str());
- }
- version.set_legal_copyright(legal_copyright.c_str());
- version.set_product_version(version_text.c_str());
- if(!godot_version.empty()) version.set_property(L"Godot Engine Version", godot_version.c_str() );
- resource_version_info_writer(res).set_version_info(file_info, strings, translations, 1033, 1200);
- if(icon_content.size()) {
- std::string icon;
- icon.resize(icon_content.size());
- for(int i=0; i<icon_content.size(); i++)
- {
- icon[i] = icon_content[i];
- }
- resource_cursor_icon_writer(res).add_icon(icon, L"MAIN_ICON", 1033);
- }
- if(image.has_resources())
- {
- rebuild_resources(image, root, image.section_from_directory(pe_win::image_directory_entry_resource));
- } else {
- section new_resources;
- new_resources.get_raw_data().resize(1);
- new_resources.set_name(".rsrc");
- new_resources.readable(true);
- section& attached_section = image.add_section(new_resources);
- rebuild_resources(image, root, attached_section);
- }
- rebuild_pe(image, p_path);
- if(image.has_overlay() && end_of_pe) {
- dst=FileAccess::open(p_path,FileAccess::READ_WRITE);
- if (dst) {
- dst->seek_end();
- DVector<uint8_t>::Read overlay_data_read = overlay_data.read();
- dst->store_buffer(overlay_data_read.ptr(),overlay_data.size());
- dst->close();
- memdelete(dst);
- }
- }
- return String();
- } catch(const pe_exception& e) {
- String ret("Error In Add rsrc Section : ");
- return ret + String(e.what());
- }
-}
diff --git a/tools/pe_bliss/pe_bliss_godot.h b/tools/pe_bliss/pe_bliss_godot.h
deleted file mode 100644
index 0365ca9eaf..0000000000
--- a/tools/pe_bliss/pe_bliss_godot.h
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-String pe_bliss_add_resrc(const char* p_path, int version_major, int version_minor,
- String& company_name, String& file_description,
- String& legal_copyright, String& version_text,
- String& product_name, String& godot_version,
- DVector<uint8_t>& icon_content);
diff --git a/tools/pe_bliss/pe_bliss_resources.h b/tools/pe_bliss/pe_bliss_resources.h
deleted file mode 100644
index 60369f8011..0000000000
--- a/tools/pe_bliss/pe_bliss_resources.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include "file_version_info.h"
-#include "message_table.h"
-#include "pe_resource_manager.h"
-#include "pe_resource_viewer.h"
-#include "version_info_editor.h"
-#include "version_info_viewer.h"
-#include "resource_bitmap_reader.h"
-#include "resource_bitmap_writer.h"
-#include "resource_cursor_icon_reader.h"
-#include "resource_cursor_icon_writer.h"
-#include "resource_version_info_reader.h"
-#include "resource_version_info_writer.h"
-#include "resource_string_table_reader.h"
-#include "resource_message_list_reader.h"
diff --git a/tools/pe_bliss/pe_bound_import.cpp b/tools/pe_bliss/pe_bound_import.cpp
deleted file mode 100644
index 4b54b36105..0000000000
--- a/tools/pe_bliss/pe_bound_import.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "pe_bound_import.h"
-#include "utils.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//BOUND IMPORT
-//Default constructor
-bound_import_ref::bound_import_ref()
- :timestamp_(0)
-{}
-
-//Constructor from data
-bound_import_ref::bound_import_ref(const std::string& module_name, uint32_t timestamp)
- :module_name_(module_name), timestamp_(timestamp)
-{}
-
-//Returns imported module name
-const std::string& bound_import_ref::get_module_name() const
-{
- return module_name_;
-}
-
-//Returns bound import date and time stamp
-uint32_t bound_import_ref::get_timestamp() const
-{
- return timestamp_;
-}
-
-//Sets module name
-void bound_import_ref::set_module_name(const std::string& module_name)
-{
- module_name_ = module_name;
-}
-
-//Sets timestamp
-void bound_import_ref::set_timestamp(uint32_t timestamp)
-{
- timestamp_ = timestamp;
-}
-
-//Default constructor
-bound_import::bound_import()
- :timestamp_(0)
-{}
-
-//Constructor from data
-bound_import::bound_import(const std::string& module_name, uint32_t timestamp)
- :module_name_(module_name), timestamp_(timestamp)
-{}
-
-//Returns imported module name
-const std::string& bound_import::get_module_name() const
-{
- return module_name_;
-}
-
-//Returns bound import date and time stamp
-uint32_t bound_import::get_timestamp() const
-{
- return timestamp_;
-}
-
-//Returns bound references cound
-size_t bound_import::get_module_ref_count() const
-{
- return refs_.size();
-}
-
-//Returns module references
-const bound_import::ref_list& bound_import::get_module_ref_list() const
-{
- return refs_;
-}
-
-//Adds module reference
-void bound_import::add_module_ref(const bound_import_ref& ref)
-{
- refs_.push_back(ref);
-}
-
-//Clears module references list
-void bound_import::clear_module_refs()
-{
- refs_.clear();
-}
-
-//Returns module references
-bound_import::ref_list& bound_import::get_module_ref_list()
-{
- return refs_;
-}
-
-//Sets module name
-void bound_import::set_module_name(const std::string& module_name)
-{
- module_name_ = module_name;
-}
-
-//Sets timestamp
-void bound_import::set_timestamp(uint32_t timestamp)
-{
- timestamp_ = timestamp;
-}
-
-const bound_import_module_list get_bound_import_module_list(const pe_base& pe)
-{
- //Returned bound import modules list
- bound_import_module_list ret;
-
- //If image has no bound imports
- if(!pe.has_bound_import())
- return ret;
-
- uint32_t bound_import_data_len =
- pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_bound_import), pe.get_directory_rva(image_directory_entry_bound_import), section_data_raw, true);
-
- if(bound_import_data_len < pe.get_directory_size(image_directory_entry_bound_import))
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- const char* bound_import_data = pe.section_data_from_rva(pe.get_directory_rva(image_directory_entry_bound_import), section_data_raw, true);
-
- //Check read in "read_pe" function raw bound import data size
- if(bound_import_data_len < sizeof(image_bound_import_descriptor))
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //current bound_import_data_ in-string position
- unsigned long current_pos = 0;
- //first bound import descriptor
- //so, we're working with raw data here, no section helpers available
- const image_bound_import_descriptor* descriptor = reinterpret_cast<const image_bound_import_descriptor*>(&bound_import_data[current_pos]);
-
- //Enumerate until zero
- while(descriptor->OffsetModuleName)
- {
- //Check module name offset
- if(descriptor->OffsetModuleName >= bound_import_data_len)
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //Check module name for null-termination
- if(!pe_utils::is_null_terminated(&bound_import_data[descriptor->OffsetModuleName], bound_import_data_len - descriptor->OffsetModuleName))
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //Create bound import descriptor structure
- bound_import elem(&bound_import_data[descriptor->OffsetModuleName], descriptor->TimeDateStamp);
-
- //Check DWORDs
- if(descriptor->NumberOfModuleForwarderRefs >= pe_utils::max_dword / sizeof(image_bound_forwarder_ref)
- || !pe_utils::is_sum_safe(current_pos, 2 /* this descriptor and the next one */ * sizeof(image_bound_import_descriptor) + descriptor->NumberOfModuleForwarderRefs * sizeof(image_bound_forwarder_ref)))
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //Move after current descriptor
- current_pos += sizeof(image_bound_import_descriptor);
-
- //Enumerate referenced bound import descriptors
- for(unsigned long i = 0; i != descriptor->NumberOfModuleForwarderRefs; ++i)
- {
- //They're just after parent descriptor
- //Check size of structure
- if(current_pos + sizeof(image_bound_forwarder_ref) > bound_import_data_len)
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //Get IMAGE_BOUND_FORWARDER_REF pointer
- const image_bound_forwarder_ref* ref_descriptor = reinterpret_cast<const image_bound_forwarder_ref*>(&bound_import_data[current_pos]);
-
- //Check referenced module name
- if(ref_descriptor->OffsetModuleName >= bound_import_data_len)
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //And its null-termination
- if(!pe_utils::is_null_terminated(&bound_import_data[ref_descriptor->OffsetModuleName], bound_import_data_len - ref_descriptor->OffsetModuleName))
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //Add referenced module to current bound import structure
- elem.add_module_ref(bound_import_ref(&bound_import_data[ref_descriptor->OffsetModuleName], ref_descriptor->TimeDateStamp));
-
- //Move after referenced bound import descriptor
- current_pos += sizeof(image_bound_forwarder_ref);
- }
-
- //Check structure size
- if(current_pos + sizeof(image_bound_import_descriptor) > bound_import_data_len)
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
-
- //Move to next bound import descriptor
- descriptor = reinterpret_cast<const image_bound_import_descriptor*>(&bound_import_data[current_pos]);
-
- //Save created descriptor structure and references
- ret.push_back(elem);
- }
-
- //Return result
- return ret;
-}
-
-//imports - bound imported modules list
-//imports_section - section where export directory will be placed (must be attached to PE image)
-//offset_from_section_start - offset from imports_section raw data start
-//save_to_pe_headers - if true, new bound import directory information will be saved to PE image headers
-//auto_strip_last_section - if true and bound imports are placed in the last section, it will be automatically stripped
-const image_directory rebuild_bound_imports(pe_base& pe, const bound_import_module_list& imports, section& imports_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section)
-{
- //Check that exports_section is attached to this PE image
- if(!pe.section_attached(imports_section))
- throw pe_exception("Bound import section must be attached to PE file", pe_exception::section_is_not_attached);
-
- uint32_t directory_pos = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t));
- uint32_t needed_size = sizeof(image_bound_import_descriptor) /* Ending null descriptor */;
- uint32_t needed_size_for_strings = 0;
-
- //Calculate needed size for bound import data
- for(bound_import_module_list::const_iterator it = imports.begin(); it != imports.end(); ++it)
- {
- const bound_import& import = *it;
- needed_size += sizeof(image_bound_import_descriptor);
- needed_size_for_strings += static_cast<uint32_t>((*it).get_module_name().length()) + 1 /* nullbyte */;
-
- const bound_import::ref_list& refs = import.get_module_ref_list();
- for(bound_import::ref_list::const_iterator ref_it = refs.begin(); ref_it != refs.end(); ++ref_it)
- {
- needed_size_for_strings += static_cast<uint32_t>((*ref_it).get_module_name().length()) + 1 /* nullbyte */;
- needed_size += sizeof(image_bound_forwarder_ref);
- }
- }
-
- needed_size += needed_size_for_strings;
-
- //Check if imports_section is last one. If it's not, check if there's enough place for bound import data
- if(&imports_section != &*(pe.get_image_sections().end() - 1) &&
- (imports_section.empty() || pe_utils::align_up(imports_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + directory_pos))
- throw pe_exception("Insufficient space for bound import directory", pe_exception::insufficient_space);
-
- std::string& raw_data = imports_section.get_raw_data();
-
- //This will be done only if imports_section is the last section of image or for section with unaligned raw length of data
- if(raw_data.length() < needed_size + directory_pos)
- raw_data.resize(needed_size + directory_pos); //Expand section raw data
-
- uint32_t current_pos_for_structures = directory_pos;
- uint32_t current_pos_for_strings = current_pos_for_structures + needed_size - needed_size_for_strings;
-
- for(bound_import_module_list::const_iterator it = imports.begin(); it != imports.end(); ++it)
- {
- const bound_import& import = *it;
- image_bound_import_descriptor descriptor;
- descriptor.NumberOfModuleForwarderRefs = static_cast<uint16_t>(import.get_module_ref_list().size());
- descriptor.OffsetModuleName = static_cast<uint16_t>(current_pos_for_strings - directory_pos);
- descriptor.TimeDateStamp = import.get_timestamp();
-
- memcpy(&raw_data[current_pos_for_structures], &descriptor, sizeof(descriptor));
- current_pos_for_structures += sizeof(descriptor);
-
- size_t length = import.get_module_name().length() + 1 /* nullbyte */;
- memcpy(&raw_data[current_pos_for_strings], import.get_module_name().c_str(), length);
- current_pos_for_strings += static_cast<uint32_t>(length);
-
- const bound_import::ref_list& refs = import.get_module_ref_list();
- for(bound_import::ref_list::const_iterator ref_it = refs.begin(); ref_it != refs.end(); ++ref_it)
- {
- const bound_import_ref& ref = *ref_it;
- image_bound_forwarder_ref ref_descriptor = {0};
- ref_descriptor.OffsetModuleName = static_cast<uint16_t>(current_pos_for_strings - directory_pos);
- ref_descriptor.TimeDateStamp = ref.get_timestamp();
-
- memcpy(&raw_data[current_pos_for_structures], &ref_descriptor, sizeof(ref_descriptor));
- current_pos_for_structures += sizeof(ref_descriptor);
-
- length = ref.get_module_name().length() + 1 /* nullbyte */;
- memcpy(&raw_data[current_pos_for_strings], ref.get_module_name().c_str(), length);
- current_pos_for_strings += static_cast<uint32_t>(length);
- }
- }
-
- //Adjust section raw and virtual sizes
- pe.recalculate_section_sizes(imports_section, auto_strip_last_section);
-
- image_directory ret(pe.rva_from_section_offset(imports_section, directory_pos), needed_size);
-
- //If auto-rewrite of PE headers is required
- if(save_to_pe_header)
- {
- pe.set_directory_rva(image_directory_entry_bound_import, ret.get_rva());
- pe.set_directory_size(image_directory_entry_bound_import, ret.get_size());
- }
-
- return ret;
-}
-}
diff --git a/tools/pe_bliss/pe_bound_import.h b/tools/pe_bliss/pe_bound_import.h
deleted file mode 100644
index 667e28792e..0000000000
--- a/tools/pe_bliss/pe_bound_import.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include <string>
-#include "pe_structures.h"
-#include "pe_base.h"
-#include "pe_directory.h"
-
-namespace pe_bliss
-{
-//Class representing bound import reference
-class bound_import_ref
-{
-public:
- //Default constructor
- bound_import_ref();
- //Constructor from data
- bound_import_ref(const std::string& module_name, uint32_t timestamp);
-
- //Returns imported module name
- const std::string& get_module_name() const;
- //Returns bound import date and time stamp
- uint32_t get_timestamp() const;
-
-public: //Setters
- //Sets module name
- void set_module_name(const std::string& module_name);
- //Sets timestamp
- void set_timestamp(uint32_t timestamp);
-
-private:
- std::string module_name_; //Imported module name
- uint32_t timestamp_; //Bound import timestamp
-};
-
-//Class representing image bound import information
-class bound_import
-{
-public:
- typedef std::vector<bound_import_ref> ref_list;
-
-public:
- //Default constructor
- bound_import();
- //Constructor from data
- bound_import(const std::string& module_name, uint32_t timestamp);
-
- //Returns imported module name
- const std::string& get_module_name() const;
- //Returns bound import date and time stamp
- uint32_t get_timestamp() const;
-
- //Returns bound references cound
- size_t get_module_ref_count() const;
- //Returns module references
- const ref_list& get_module_ref_list() const;
-
-public: //Setters
- //Sets module name
- void set_module_name(const std::string& module_name);
- //Sets timestamp
- void set_timestamp(uint32_t timestamp);
-
- //Adds module reference
- void add_module_ref(const bound_import_ref& ref);
- //Clears module references list
- void clear_module_refs();
- //Returns module references
- ref_list& get_module_ref_list();
-
-private:
- std::string module_name_; //Imported module name
- uint32_t timestamp_; //Bound import timestamp
- ref_list refs_; //Module references list
-};
-
-typedef std::vector<bound_import> bound_import_module_list;
-
-//Returns bound import information
-const bound_import_module_list get_bound_import_module_list(const pe_base& pe);//Export directory rebuilder
-
-//imports - bound imported modules list
-//imports_section - section where export directory will be placed (must be attached to PE image)
-//offset_from_section_start - offset from imports_section raw data start
-//save_to_pe_headers - if true, new bound import directory information will be saved to PE image headers
-//auto_strip_last_section - if true and bound imports are placed in the last section, it will be automatically stripped
-const image_directory rebuild_bound_imports(pe_base& pe, const bound_import_module_list& imports, section& imports_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-}
diff --git a/tools/pe_bliss/pe_checksum.cpp b/tools/pe_bliss/pe_checksum.cpp
deleted file mode 100644
index 5971a33c90..0000000000
--- a/tools/pe_bliss/pe_checksum.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_checksum.h"
-#include "pe_structures.h"
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Calculate checksum of image
-uint32_t calculate_checksum(std::istream& file)
-{
- //Save istream state
- std::ios_base::iostate state = file.exceptions();
- std::streamoff old_offset = file.tellg();
-
- //Checksum value
- unsigned long long checksum = 0;
-
- try
- {
- image_dos_header header;
-
- file.exceptions(std::ios::goodbit);
-
- //Read DOS header
- pe_base::read_dos_header(file, header);
-
- //Calculate PE checksum
- file.seekg(0);
- unsigned long long top = 0xFFFFFFFF;
- top++;
-
- //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
- static const unsigned long checksum_pos_in_optional_headers = 64;
- //Calculate real PE headers "CheckSum" field position
- //Sum is safe here
- unsigned long pe_checksum_pos = header.e_lfanew + sizeof(image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
-
- //Calculate checksum for each byte of file
- std::streamoff filesize = pe_utils::get_file_size(file);
- for(long long i = 0; i < filesize; i += 4)
- {
- unsigned long dw = 0;
-
- //Read DWORD from file
- file.read(reinterpret_cast<char*>(&dw), sizeof(unsigned long));
- //Skip "CheckSum" DWORD
- if(i == pe_checksum_pos)
- continue;
-
- //Calculate checksum
- checksum = (checksum & 0xffffffff) + dw + (checksum >> 32);
- if(checksum > top)
- checksum = (checksum & 0xffffffff) + (checksum >> 32);
- }
-
- //Finish checksum
- checksum = (checksum & 0xffff) + (checksum >> 16);
- checksum = (checksum) + (checksum >> 16);
- checksum = checksum & 0xffff;
-
- checksum += static_cast<unsigned long>(filesize);
- }
- catch(const std::exception&)
- {
- //If something went wrong, restore istream state
- file.exceptions(state);
- file.seekg(old_offset);
- file.clear();
- //Rethrow
- throw;
- }
-
- //Restore istream state
- file.exceptions(state);
- file.seekg(old_offset);
- file.clear();
-
- //Return checksum
- return static_cast<uint32_t>(checksum);
-}
-}
diff --git a/tools/pe_bliss/pe_checksum.h b/tools/pe_bliss/pe_checksum.h
deleted file mode 100644
index a568d5d369..0000000000
--- a/tools/pe_bliss/pe_checksum.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <istream>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-//Calculate checksum of image (performs no checks on PE structures)
-uint32_t calculate_checksum(std::istream& file);
-}
diff --git a/tools/pe_bliss/pe_debug.cpp b/tools/pe_bliss/pe_debug.cpp
deleted file mode 100644
index a0ed3f5af1..0000000000
--- a/tools/pe_bliss/pe_debug.cpp
+++ /dev/null
@@ -1,865 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "pe_debug.h"
-#include "utils.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-//DEBUG
-//Default constructor
-debug_info::debug_info()
- :characteristics_(0),
- time_stamp_(0),
- major_version_(0), minor_version_(0),
- type_(0),
- size_of_data_(0),
- address_of_raw_data_(0),
- pointer_to_raw_data_(0),
- advanced_info_type_(advanced_info_none)
-{}
-
-//Constructor from data
-debug_info::debug_info(const image_debug_directory& debug)
- :characteristics_(debug.Characteristics),
- time_stamp_(debug.TimeDateStamp),
- major_version_(debug.MajorVersion), minor_version_(debug.MinorVersion),
- type_(debug.Type),
- size_of_data_(debug.SizeOfData),
- address_of_raw_data_(debug.AddressOfRawData),
- pointer_to_raw_data_(debug.PointerToRawData),
- advanced_info_type_(advanced_info_none)
-{}
-
-//Returns debug characteristics
-uint32_t debug_info::get_characteristics() const
-{
- return characteristics_;
-}
-
-//Returns debug datetimestamp
-uint32_t debug_info::get_time_stamp() const
-{
- return time_stamp_;
-}
-
-//Returns major version
-uint32_t debug_info::get_major_version() const
-{
- return major_version_;
-}
-
-//Returns minor version
-uint32_t debug_info::get_minor_version() const
-{
- return minor_version_;
-}
-
-//Returns type of debug info (unchecked)
-uint32_t debug_info::get_type_raw() const
-{
- return type_;
-}
-
-//Returns type of debug info from debug_info_type enumeration
-debug_info::debug_info_type debug_info::get_type() const
-{
- //Determine debug type
- switch(type_)
- {
- case image_debug_type_coff:
- return debug_type_coff;
-
- case image_debug_type_codeview:
- return debug_type_codeview;
-
- case image_debug_type_fpo:
- return debug_type_fpo;
-
- case image_debug_type_misc:
- return debug_type_misc;
-
- case image_debug_type_exception:
- return debug_type_exception;
-
- case image_debug_type_fixup:
- return debug_type_fixup;
-
- case image_debug_type_omap_to_src:
- return debug_type_omap_to_src;
-
- case image_debug_type_omap_from_src:
- return debug_type_omap_from_src;
-
- case image_debug_type_borland:
- return debug_type_borland;
-
- case image_debug_type_clsid:
- return debug_type_clsid;
-
- case image_debug_type_reserved10:
- return debug_type_reserved10;
- }
-
- return debug_type_unknown;
-}
-
-//Returns size of debug data (internal, .pdb or other file doesn't count)
-uint32_t debug_info::get_size_of_data() const
-{
- return size_of_data_;
-}
-
-//Returns RVA of debug info when mapped to memory or zero, if info is not mapped
-uint32_t debug_info::get_rva_of_raw_data() const
-{
- return address_of_raw_data_;
-}
-
-//Returns raw file pointer to raw data
-uint32_t debug_info::get_pointer_to_raw_data() const
-{
- return pointer_to_raw_data_;
-}
-
-//Copy constructor
-debug_info::debug_info(const debug_info& info)
- :characteristics_(info.characteristics_),
- time_stamp_(info.time_stamp_),
- major_version_(info.major_version_), minor_version_(info.minor_version_),
- type_(info.type_),
- size_of_data_(info.size_of_data_),
- address_of_raw_data_(info.address_of_raw_data_),
- pointer_to_raw_data_(info.pointer_to_raw_data_),
- advanced_info_type_(info.advanced_info_type_)
-{
- copy_advanced_info(info);
-}
-
-//Copy assignment operator
-debug_info& debug_info::operator=(const debug_info& info)
-{
- copy_advanced_info(info);
-
- characteristics_ = info.characteristics_;
- time_stamp_ = info.time_stamp_;
- major_version_ = info.major_version_;
- minor_version_ = info.minor_version_;
- type_ = info.type_;
- size_of_data_ = info.size_of_data_;
- address_of_raw_data_ = info.address_of_raw_data_;
- pointer_to_raw_data_ = info.pointer_to_raw_data_;
- advanced_info_type_ = info.advanced_info_type_;
-
- return *this;
-}
-
-//Default constructor
-debug_info::advanced_info::advanced_info()
- :adv_pdb_7_0_info(0) //Zero pointer to advanced data
-{}
-
-//Returns true if advanced debug info is present
-bool debug_info::advanced_info::is_present() const
-{
- return adv_pdb_7_0_info != 0;
-}
-
-//Helper for advanced debug information copying
-void debug_info::copy_advanced_info(const debug_info& info)
-{
- free_present_advanced_info();
-
- switch(info.advanced_info_type_)
- {
- case advanced_info_pdb_7_0:
- advanced_debug_info_.adv_pdb_7_0_info = new pdb_7_0_info(*info.advanced_debug_info_.adv_pdb_7_0_info);
- break;
- case advanced_info_pdb_2_0:
- advanced_debug_info_.adv_pdb_2_0_info = new pdb_2_0_info(*info.advanced_debug_info_.adv_pdb_2_0_info);
- break;
- case advanced_info_misc:
- advanced_debug_info_.adv_misc_info = new misc_debug_info(*info.advanced_debug_info_.adv_misc_info);
- break;
- case advanced_info_coff:
- advanced_debug_info_.adv_coff_info = new coff_debug_info(*info.advanced_debug_info_.adv_coff_info);
- break;
- default:
- break;
- }
-
- advanced_info_type_ = info.advanced_info_type_;
-}
-
-//Helper for clearing any present advanced debug information
-void debug_info::free_present_advanced_info()
-{
- switch(advanced_info_type_)
- {
- case advanced_info_pdb_7_0:
- delete advanced_debug_info_.adv_pdb_7_0_info;
- break;
- case advanced_info_pdb_2_0:
- delete advanced_debug_info_.adv_pdb_2_0_info;
- break;
- case advanced_info_misc:
- delete advanced_debug_info_.adv_misc_info;
- break;
- case advanced_info_coff:
- delete advanced_debug_info_.adv_coff_info;
- break;
- default:
- break;
- }
-
- advanced_debug_info_.adv_pdb_7_0_info = 0;
- advanced_info_type_ = advanced_info_none;
-}
-
-//Destructor
-debug_info::~debug_info()
-{
- free_present_advanced_info();
-}
-
-//Sets advanced debug information
-void debug_info::set_advanced_debug_info(const pdb_7_0_info& info)
-{
- free_present_advanced_info();
- advanced_debug_info_.adv_pdb_7_0_info = new pdb_7_0_info(info);
- advanced_info_type_ = advanced_info_pdb_7_0;
-}
-
-void debug_info::set_advanced_debug_info(const pdb_2_0_info& info)
-{
- free_present_advanced_info();
- advanced_debug_info_.adv_pdb_2_0_info = new pdb_2_0_info(info);
- advanced_info_type_ = advanced_info_pdb_2_0;
-}
-
-void debug_info::set_advanced_debug_info(const misc_debug_info& info)
-{
- free_present_advanced_info();
- advanced_debug_info_.adv_misc_info = new misc_debug_info(info);
- advanced_info_type_ = advanced_info_misc;
-}
-
-void debug_info::set_advanced_debug_info(const coff_debug_info& info)
-{
- free_present_advanced_info();
- advanced_debug_info_.adv_coff_info = new coff_debug_info(info);
- advanced_info_type_ = advanced_info_coff;
-}
-
-//Returns advanced debug information type
-debug_info::advanced_info_type debug_info::get_advanced_info_type() const
-{
- return advanced_info_type_;
-}
-
-//Returns advanced debug information or throws an exception,
-//if requested information type is not contained by structure
-template<>
-const pdb_7_0_info debug_info::get_advanced_debug_info<pdb_7_0_info>() const
-{
- if(advanced_info_type_ != advanced_info_pdb_7_0)
- throw pe_exception("Debug info structure does not contain PDB 7.0 data", pe_exception::advanced_debug_information_request_error);
-
- return *advanced_debug_info_.adv_pdb_7_0_info;
-}
-
-template<>
-const pdb_2_0_info debug_info::get_advanced_debug_info<pdb_2_0_info>() const
-{
- if(advanced_info_type_ != advanced_info_pdb_2_0)
- throw pe_exception("Debug info structure does not contain PDB 2.0 data", pe_exception::advanced_debug_information_request_error);
-
- return *advanced_debug_info_.adv_pdb_2_0_info;
-}
-
-template<>
-const misc_debug_info debug_info::get_advanced_debug_info<misc_debug_info>() const
-{
- if(advanced_info_type_ != advanced_info_misc)
- throw pe_exception("Debug info structure does not contain MISC data", pe_exception::advanced_debug_information_request_error);
-
- return *advanced_debug_info_.adv_misc_info;
-}
-
-template<>
-const coff_debug_info debug_info::get_advanced_debug_info<coff_debug_info>() const
-{
- if(advanced_info_type_ != advanced_info_coff)
- throw pe_exception("Debug info structure does not contain COFF data", pe_exception::advanced_debug_information_request_error);
-
- return *advanced_debug_info_.adv_coff_info;
-}
-
-//Sets advanced debug information type, if no advanced info structure available
-void debug_info::set_advanced_info_type(advanced_info_type type)
-{
- free_present_advanced_info();
- if(advanced_info_type_ >= advanced_info_codeview_4_0) //Don't set info type for those types, which have advanced info structures
- advanced_info_type_ = type;
-}
-
-//Default constructor
-pdb_7_0_info::pdb_7_0_info()
- :age_(0)
-{
- memset(&guid_, 0, sizeof(guid_));
-}
-
-//Constructor from data
-pdb_7_0_info::pdb_7_0_info(const CV_INFO_PDB70* info)
- :age_(info->Age), guid_(info->Signature),
- pdb_file_name_(reinterpret_cast<const char*>(info->PdbFileName)) //Must be checked before for null-termination
-{}
-
-//Returns debug PDB 7.0 structure GUID
-const guid pdb_7_0_info::get_guid() const
-{
- return guid_;
-}
-
-//Returns age of build
-uint32_t pdb_7_0_info::get_age() const
-{
- return age_;
-}
-
-//Returns PDB file name / path
-const std::string& pdb_7_0_info::get_pdb_file_name() const
-{
- return pdb_file_name_;
-}
-
-//Default constructor
-pdb_2_0_info::pdb_2_0_info()
- :age_(0), signature_(0)
-{}
-
-//Constructor from data
-pdb_2_0_info::pdb_2_0_info(const CV_INFO_PDB20* info)
- :age_(info->Age), signature_(info->Signature),
- pdb_file_name_(reinterpret_cast<const char*>(info->PdbFileName)) //Must be checked before for null-termination
-{}
-
-//Returns debug PDB 2.0 structure signature
-uint32_t pdb_2_0_info::get_signature() const
-{
- return signature_;
-}
-
-//Returns age of build
-uint32_t pdb_2_0_info::get_age() const
-{
- return age_;
-}
-
-//Returns PDB file name / path
-const std::string& pdb_2_0_info::get_pdb_file_name() const
-{
- return pdb_file_name_;
-}
-
-//Default constructor
-misc_debug_info::misc_debug_info()
- :data_type_(0), unicode_(false)
-{}
-
-//Constructor from data
-misc_debug_info::misc_debug_info(const image_debug_misc* info)
- :data_type_(info->DataType), unicode_(info->Unicode ? true : false)
-{
- //IMAGE_DEBUG_MISC::Data must be checked before!
- if(info->Unicode)
- {
-#ifdef PE_BLISS_WINDOWS
- debug_data_unicode_ = std::wstring(reinterpret_cast<const wchar_t*>(info->Data), (info->Length - sizeof(image_debug_misc) + 1 /* BYTE[1] in the end of structure */) / 2);
-#else
- debug_data_unicode_ = pe_utils::from_ucs2(u16string(reinterpret_cast<const unicode16_t*>(info->Data), (info->Length - sizeof(image_debug_misc) + 1 /* BYTE[1] in the end of structure */) / 2));
-#endif
-
- pe_utils::strip_nullbytes(debug_data_unicode_); //Strip nullbytes in the end of string
- }
- else
- {
- debug_data_ansi_ = std::string(reinterpret_cast<const char*>(info->Data), info->Length - sizeof(image_debug_misc) + 1 /* BYTE[1] in the end of structure */);
- pe_utils::strip_nullbytes(debug_data_ansi_); //Strip nullbytes in the end of string
- }
-}
-
-//Returns debug data type
-uint32_t misc_debug_info::get_data_type() const
-{
- return data_type_;
-}
-
-//Returns true if data type is exe name
-bool misc_debug_info::is_exe_name() const
-{
- return data_type_ == image_debug_misc_exename;
-}
-
-//Returns true if debug data is UNICODE
-bool misc_debug_info::is_unicode() const
-{
- return unicode_;
-}
-
-//Returns debug data (ANSI)
-const std::string& misc_debug_info::get_data_ansi() const
-{
- return debug_data_ansi_;
-}
-
-//Returns debug data (UNICODE)
-const std::wstring& misc_debug_info::get_data_unicode() const
-{
- return debug_data_unicode_;
-}
-
-//Default constructor
-coff_debug_info::coff_debug_info()
- :number_of_symbols_(0),
- lva_to_first_symbol_(0),
- number_of_line_numbers_(0),
- lva_to_first_line_number_(0),
- rva_to_first_byte_of_code_(0),
- rva_to_last_byte_of_code_(0),
- rva_to_first_byte_of_data_(0),
- rva_to_last_byte_of_data_(0)
-{}
-
-//Constructor from data
-coff_debug_info::coff_debug_info(const image_coff_symbols_header* info)
- :number_of_symbols_(info->NumberOfSymbols),
- lva_to_first_symbol_(info->LvaToFirstSymbol),
- number_of_line_numbers_(info->NumberOfLinenumbers),
- lva_to_first_line_number_(info->LvaToFirstLinenumber),
- rva_to_first_byte_of_code_(info->RvaToFirstByteOfCode),
- rva_to_last_byte_of_code_(info->RvaToLastByteOfCode),
- rva_to_first_byte_of_data_(info->RvaToFirstByteOfData),
- rva_to_last_byte_of_data_(info->RvaToLastByteOfData)
-{}
-
-//Returns number of symbols
-uint32_t coff_debug_info::get_number_of_symbols() const
-{
- return number_of_symbols_;
-}
-
-//Returns virtual address of the first symbol
-uint32_t coff_debug_info::get_lva_to_first_symbol() const
-{
- return lva_to_first_symbol_;
-}
-
-//Returns number of line-number entries
-uint32_t coff_debug_info::get_number_of_line_numbers() const
-{
- return number_of_line_numbers_;
-}
-
-//Returns virtual address of the first line-number entry
-uint32_t coff_debug_info::get_lva_to_first_line_number() const
-{
- return lva_to_first_line_number_;
-}
-
-//Returns relative virtual address of the first byte of code
-uint32_t coff_debug_info::get_rva_to_first_byte_of_code() const
-{
- return rva_to_first_byte_of_code_;
-}
-
-//Returns relative virtual address of the last byte of code
-uint32_t coff_debug_info::get_rva_to_last_byte_of_code() const
-{
- return rva_to_last_byte_of_code_;
-}
-
-//Returns relative virtual address of the first byte of data
-uint32_t coff_debug_info::get_rva_to_first_byte_of_data() const
-{
- return rva_to_first_byte_of_data_;
-}
-
-//Returns relative virtual address of the last byte of data
-uint32_t coff_debug_info::get_rva_to_last_byte_of_data() const
-{
- return rva_to_last_byte_of_data_;
-}
-
-//Returns COFF symbols list
-const coff_debug_info::coff_symbols_list& coff_debug_info::get_symbols() const
-{
- return symbols_;
-}
-
-//Adds COFF symbol
-void coff_debug_info::add_symbol(const coff_symbol& sym)
-{
- symbols_.push_back(sym);
-}
-
-//Default constructor
-coff_debug_info::coff_symbol::coff_symbol()
- :storage_class_(0),
- index_(0),
- section_number_(0), rva_(0),
- type_(0),
- is_filename_(false)
-{}
-
-//Returns storage class
-uint32_t coff_debug_info::coff_symbol::get_storage_class() const
-{
- return storage_class_;
-}
-
-//Returns symbol index
-uint32_t coff_debug_info::coff_symbol::get_index() const
-{
- return index_;
-}
-
-//Returns section number
-uint32_t coff_debug_info::coff_symbol::get_section_number() const
-{
- return section_number_;
-}
-
-//Returns RVA
-uint32_t coff_debug_info::coff_symbol::get_rva() const
-{
- return rva_;
-}
-
-//Returns true if structure contains file name
-bool coff_debug_info::coff_symbol::is_file() const
-{
- return is_filename_;
-}
-
-//Returns text data (symbol or file name)
-const std::string& coff_debug_info::coff_symbol::get_symbol() const
-{
- return name_;
-}
-
-//Sets storage class
-void coff_debug_info::coff_symbol::set_storage_class(uint32_t storage_class)
-{
- storage_class_ = storage_class;
-}
-
-//Sets symbol index
-void coff_debug_info::coff_symbol::set_index(uint32_t index)
-{
- index_ = index;
-}
-
-//Sets section number
-void coff_debug_info::coff_symbol::set_section_number(uint32_t section_number)
-{
- section_number_ = section_number;
-}
-
-//Sets RVA
-void coff_debug_info::coff_symbol::set_rva(uint32_t rva)
-{
- rva_ = rva;
-}
-
-//Sets file name
-void coff_debug_info::coff_symbol::set_file_name(const std::string& file_name)
-{
- name_ = file_name;
- is_filename_ = true;
-}
-
-//Sets symbol name
-void coff_debug_info::coff_symbol::set_symbol_name(const std::string& symbol_name)
-{
- name_ = symbol_name;
- is_filename_ = false;
-}
-
-//Returns type
-uint16_t coff_debug_info::coff_symbol::get_type() const
-{
- return type_;
-}
-
-//Sets type
-void coff_debug_info::coff_symbol::set_type(uint16_t type)
-{
- type_ = type;
-}
-
-//Returns debug information list
-const debug_info_list get_debug_information(const pe_base& pe)
-{
- debug_info_list ret;
-
- //If there's no debug directory, return empty list
- if(!pe.has_debug())
- return ret;
-
- //Check the length in bytes of the section containing debug directory
- if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_debug), pe.get_directory_rva(image_directory_entry_debug), section_data_virtual, true)
- < sizeof(image_debug_directory))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- unsigned long current_pos = pe.get_directory_rva(image_directory_entry_debug);
-
- //First IMAGE_DEBUG_DIRECTORY table
- image_debug_directory directory = pe.section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true);
-
- if(!pe_utils::is_sum_safe(pe.get_directory_rva(image_directory_entry_debug), pe.get_directory_size(image_directory_entry_debug)))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Iterate over all IMAGE_DEBUG_DIRECTORY directories
- while(directory.PointerToRawData
- && current_pos < pe.get_directory_rva(image_directory_entry_debug) + pe.get_directory_size(image_directory_entry_debug))
- {
- //Create debug information structure
- debug_info info(directory);
-
- //Find raw debug data
- const pe_base::debug_data_list& debug_datas = pe.get_raw_debug_data_list();
- pe_base::debug_data_list::const_iterator it = debug_datas.find(directory.PointerToRawData);
- if(it != debug_datas.end()) //If it exists, we'll do some detailed debug info research
- {
- const std::string& debug_data = (*it).second;
- switch(directory.Type)
- {
- case image_debug_type_coff:
- {
- //Check data length
- if(debug_data.length() < sizeof(image_coff_symbols_header))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Get coff header structure pointer
- const image_coff_symbols_header* coff = reinterpret_cast<const image_coff_symbols_header*>(debug_data.data());
-
- //Check possible overflows
- if(coff->NumberOfSymbols >= pe_utils::max_dword / sizeof(image_symbol)
- || !pe_utils::is_sum_safe(coff->NumberOfSymbols * sizeof(image_symbol), coff->LvaToFirstSymbol))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Check data length again
- if(debug_data.length() < coff->NumberOfSymbols * sizeof(image_symbol) + coff->LvaToFirstSymbol)
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Create COFF debug info structure
- coff_debug_info coff_info(coff);
-
- //Enumerate debug symbols data
- for(uint32_t i = 0; i < coff->NumberOfSymbols; ++i)
- {
- //Safe sum (checked above)
- const image_symbol* sym = reinterpret_cast<const image_symbol*>(debug_data.data() + i * sizeof(image_symbol) + coff->LvaToFirstSymbol);
-
- coff_debug_info::coff_symbol symbol;
- symbol.set_index(i); //Save symbol index
- symbol.set_storage_class(sym->StorageClass); //Save storage class
- symbol.set_type(sym->Type); //Save storage class
-
- //Check data length again
- if(!pe_utils::is_sum_safe(i, sym->NumberOfAuxSymbols)
- || (i + sym->NumberOfAuxSymbols) > coff->NumberOfSymbols
- || debug_data.length() < (i + 1) * sizeof(image_symbol) + coff->LvaToFirstSymbol + sym->NumberOfAuxSymbols * sizeof(image_symbol))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //If symbol is filename
- if(sym->StorageClass == image_sym_class_file)
- {
- //Save file name, it is situated just after this IMAGE_SYMBOL structure
- std::string file_name(reinterpret_cast<const char*>(debug_data.data() + (i + 1) * sizeof(image_symbol)), sym->NumberOfAuxSymbols * sizeof(image_symbol));
- pe_utils::strip_nullbytes(file_name);
- symbol.set_file_name(file_name);
-
- //Save symbol info
- coff_info.add_symbol(symbol);
-
- //Move to next symbol
- i += sym->NumberOfAuxSymbols;
- continue;
- }
-
- //Dump some other symbols
- if(((sym->StorageClass == image_sym_class_static)
- && (sym->NumberOfAuxSymbols == 0)
- && (sym->SectionNumber == 1))
- ||
- ((sym->StorageClass == image_sym_class_external)
- && ISFCN(sym->Type)
- && (sym->SectionNumber > 0))
- )
- {
- //Save RVA and section number
- symbol.set_section_number(sym->SectionNumber);
- symbol.set_rva(sym->Value);
-
- //If symbol has short name
- if(sym->N.Name.Short)
- {
- //Copy and save symbol name
- char name_buff[9];
- memcpy(name_buff, sym->N.ShortName, 8);
- name_buff[8] = '\0';
- symbol.set_symbol_name(name_buff);
- }
- else
- {
- //Symbol has long name
-
- //Check possible overflows
- if(!pe_utils::is_sum_safe(coff->LvaToFirstSymbol + coff->NumberOfSymbols * sizeof(image_symbol), sym->N.Name.Long))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Here we have an offset to the string table
- uint32_t symbol_offset = coff->LvaToFirstSymbol + coff->NumberOfSymbols * sizeof(image_symbol) + sym->N.Name.Long;
-
- //Check data length
- if(debug_data.length() < symbol_offset)
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Check symbol name for null-termination
- if(!pe_utils::is_null_terminated(debug_data.data() + symbol_offset, debug_data.length() - symbol_offset))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Save symbol name
- symbol.set_symbol_name(debug_data.data() + symbol_offset);
- }
-
- //Save symbol info
- coff_info.add_symbol(symbol);
-
- //Move to next symbol
- i += sym->NumberOfAuxSymbols;
- continue;
- }
- }
-
- info.set_advanced_debug_info(coff_info);
- }
- break;
-
- case image_debug_type_codeview:
- {
- //Check data length
- if(debug_data.length() < sizeof(OMFSignature*))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Get POMFSignature structure pointer from the very beginning of debug data
- const OMFSignature* sig = reinterpret_cast<const OMFSignature*>(debug_data.data());
- if(!memcmp(sig->Signature, "RSDS", 4))
- {
- //Signature is "RSDS" - PDB 7.0
-
- //Check data length
- if(debug_data.length() < sizeof(CV_INFO_PDB70))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- const CV_INFO_PDB70* pdb_data = reinterpret_cast<const CV_INFO_PDB70*>(debug_data.data());
-
- //Check PDB file name null-termination
- if(!pe_utils::is_null_terminated(pdb_data->PdbFileName, debug_data.length() - (sizeof(CV_INFO_PDB70) - 1 /* BYTE of filename in structure */)))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- info.set_advanced_debug_info(pdb_7_0_info(pdb_data));
- }
- else if(!memcmp(sig->Signature, "NB10", 4))
- {
- //Signature is "NB10" - PDB 2.0
-
- //Check data length
- if(debug_data.length() < sizeof(CV_INFO_PDB20))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- const CV_INFO_PDB20* pdb_data = reinterpret_cast<const CV_INFO_PDB20*>(debug_data.data());
-
- //Check PDB file name null-termination
- if(!pe_utils::is_null_terminated(pdb_data->PdbFileName, debug_data.length() - (sizeof(CV_INFO_PDB20) - 1 /* BYTE of filename in structure */)))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- info.set_advanced_debug_info(pdb_2_0_info(pdb_data));
- }
- else if(!memcmp(sig->Signature, "NB09", 4))
- {
- //CodeView 4.0, no structures available
- info.set_advanced_info_type(debug_info::advanced_info_codeview_4_0);
- }
- else if(!memcmp(sig->Signature, "NB11", 4))
- {
- //CodeView 5.0, no structures available
- info.set_advanced_info_type(debug_info::advanced_info_codeview_5_0);
- }
- else if(!memcmp(sig->Signature, "NB05", 4))
- {
- //Other CodeView, no structures available
- info.set_advanced_info_type(debug_info::advanced_info_codeview);
- }
- }
-
- break;
-
- case image_debug_type_misc:
- {
- //Check data length
- if(debug_data.length() < sizeof(image_debug_misc))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Get misc structure pointer
- const image_debug_misc* misc_data = reinterpret_cast<const image_debug_misc*>(debug_data.data());
-
- //Check misc data length
- if(debug_data.length() < misc_data->Length /* Total length of record */)
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Save advanced information
- info.set_advanced_debug_info(misc_debug_info(misc_data));
- }
- break;
- }
- }
-
- //Save debug information structure
- ret.push_back(info);
-
- //Check possible overflow
- if(!pe_utils::is_sum_safe(current_pos, sizeof(image_debug_directory)))
- throw pe_exception("Incorrect debug directory", pe_exception::incorrect_debug_directory);
-
- //Go to next debug entry
- current_pos += sizeof(image_debug_directory);
- directory = pe.section_data_from_rva<image_debug_directory>(current_pos, section_data_virtual, true);
- }
-
- return ret;
-}
-}
diff --git a/tools/pe_bliss/pe_debug.h b/tools/pe_bliss/pe_debug.h
deleted file mode 100644
index 73a7e6860d..0000000000
--- a/tools/pe_bliss/pe_debug.h
+++ /dev/null
@@ -1,324 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include "pe_structures.h"
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-//Class representing advanced RSDS (PDB 7.0) information
-class pdb_7_0_info
-{
-public:
- //Default constructor
- pdb_7_0_info();
- //Constructor from data
- explicit pdb_7_0_info(const pe_win::CV_INFO_PDB70* info);
-
- //Returns debug PDB 7.0 structure GUID
- const pe_win::guid get_guid() const;
- //Returns age of build
- uint32_t get_age() const;
- //Returns PDB file name / path
- const std::string& get_pdb_file_name() const;
-
-private:
- uint32_t age_;
- pe_win::guid guid_;
- std::string pdb_file_name_;
-};
-
-//Class representing advanced NB10 (PDB 2.0) information
-class pdb_2_0_info
-{
-public:
- //Default constructor
- pdb_2_0_info();
- //Constructor from data
- explicit pdb_2_0_info(const pe_win::CV_INFO_PDB20* info);
-
- //Returns debug PDB 2.0 structure signature
- uint32_t get_signature() const;
- //Returns age of build
- uint32_t get_age() const;
- //Returns PDB file name / path
- const std::string& get_pdb_file_name() const;
-
-private:
- uint32_t age_;
- uint32_t signature_;
- std::string pdb_file_name_;
-};
-
-//Class representing advanced misc (IMAGE_DEBUG_TYPE_MISC) info
-class misc_debug_info
-{
-public:
- //Default constructor
- misc_debug_info();
- //Constructor from data
- explicit misc_debug_info(const pe_win::image_debug_misc* info);
-
- //Returns debug data type
- uint32_t get_data_type() const;
- //Returns true if data type is exe name
- bool is_exe_name() const;
-
- //Returns true if debug data is UNICODE
- bool is_unicode() const;
- //Returns debug data (ANSI or UNICODE)
- const std::string& get_data_ansi() const;
- const std::wstring& get_data_unicode() const;
-
-private:
- uint32_t data_type_;
- bool unicode_;
- std::string debug_data_ansi_;
- std::wstring debug_data_unicode_;
-};
-
-//Class representing COFF (IMAGE_DEBUG_TYPE_COFF) debug info
-class coff_debug_info
-{
-public:
- //Structure representing COFF symbol
- struct coff_symbol
- {
- public:
- //Default constructor
- coff_symbol();
-
- //Returns storage class
- uint32_t get_storage_class() const;
- //Returns symbol index
- uint32_t get_index() const;
- //Returns section number
- uint32_t get_section_number() const;
- //Returns RVA
- uint32_t get_rva() const;
- //Returns type
- uint16_t get_type() const;
-
- //Returns true if structure contains file name
- bool is_file() const;
- //Returns text data (symbol or file name)
- const std::string& get_symbol() const;
-
- public: //These functions do not change everything inside image, they are used by PE class
- //Sets storage class
- void set_storage_class(uint32_t storage_class);
- //Sets symbol index
- void set_index(uint32_t index);
- //Sets section number
- void set_section_number(uint32_t section_number);
- //Sets RVA
- void set_rva(uint32_t rva);
- //Sets type
- void set_type(uint16_t type);
-
- //Sets file name
- void set_file_name(const std::string& file_name);
- //Sets symbol name
- void set_symbol_name(const std::string& symbol_name);
-
- private:
- uint32_t storage_class_;
- uint32_t index_;
- uint32_t section_number_, rva_;
- uint16_t type_;
- bool is_filename_;
- std::string name_;
- };
-
-public:
- typedef std::vector<coff_symbol> coff_symbols_list;
-
-public:
- //Default constructor
- coff_debug_info();
- //Constructor from data
- explicit coff_debug_info(const pe_win::image_coff_symbols_header* info);
-
- //Returns number of symbols
- uint32_t get_number_of_symbols() const;
- //Returns virtual address of the first symbol
- uint32_t get_lva_to_first_symbol() const;
- //Returns number of line-number entries
- uint32_t get_number_of_line_numbers() const;
- //Returns virtual address of the first line-number entry
- uint32_t get_lva_to_first_line_number() const;
- //Returns relative virtual address of the first byte of code
- uint32_t get_rva_to_first_byte_of_code() const;
- //Returns relative virtual address of the last byte of code
- uint32_t get_rva_to_last_byte_of_code() const;
- //Returns relative virtual address of the first byte of data
- uint32_t get_rva_to_first_byte_of_data() const;
- //Returns relative virtual address of the last byte of data
- uint32_t get_rva_to_last_byte_of_data() const;
-
- //Returns COFF symbols list
- const coff_symbols_list& get_symbols() const;
-
-public: //These functions do not change everything inside image, they are used by PE class
- //Adds COFF symbol
- void add_symbol(const coff_symbol& sym);
-
-private:
- uint32_t number_of_symbols_;
- uint32_t lva_to_first_symbol_;
- uint32_t number_of_line_numbers_;
- uint32_t lva_to_first_line_number_;
- uint32_t rva_to_first_byte_of_code_;
- uint32_t rva_to_last_byte_of_code_;
- uint32_t rva_to_first_byte_of_data_;
- uint32_t rva_to_last_byte_of_data_;
-
-private:
- coff_symbols_list symbols_;
-};
-
-//Class representing debug information
-class debug_info
-{
-public:
- //Enumeration of debug information types
- enum debug_info_type
- {
- debug_type_unknown,
- debug_type_coff,
- debug_type_codeview,
- debug_type_fpo,
- debug_type_misc,
- debug_type_exception,
- debug_type_fixup,
- debug_type_omap_to_src,
- debug_type_omap_from_src,
- debug_type_borland,
- debug_type_reserved10,
- debug_type_clsid
- };
-
-public:
- //Enumeration of advanced debug information types
- enum advanced_info_type
- {
- advanced_info_none, //No advanced info
- advanced_info_pdb_7_0, //PDB 7.0
- advanced_info_pdb_2_0, //PDB 2.0
- advanced_info_misc, //MISC debug info
- advanced_info_coff, //COFF debug info
- //No advanced info structures available for types below
- advanced_info_codeview_4_0, //CodeView 4.0
- advanced_info_codeview_5_0, //CodeView 5.0
- advanced_info_codeview //CodeView
- };
-
-public:
- //Default constructor
- debug_info();
- //Constructor from data
- explicit debug_info(const pe_win::image_debug_directory& debug);
- //Copy constructor
- debug_info(const debug_info& info);
- //Copy assignment operator
- debug_info& operator=(const debug_info& info);
- //Destructor
- ~debug_info();
-
- //Returns debug characteristics
- uint32_t get_characteristics() const;
- //Returns debug datetimestamp
- uint32_t get_time_stamp() const;
- //Returns major version
- uint32_t get_major_version() const;
- //Returns minor version
- uint32_t get_minor_version() const;
- //Returns type of debug info (unchecked)
- uint32_t get_type_raw() const;
- //Returns type of debug info from debug_info_type enumeration
- debug_info_type get_type() const;
- //Returns size of debug data (internal, .pdb or other file doesn't count)
- uint32_t get_size_of_data() const;
- //Returns RVA of debug info when mapped to memory or zero, if info is not mapped
- uint32_t get_rva_of_raw_data() const;
- //Returns raw file pointer to raw data
- uint32_t get_pointer_to_raw_data() const;
-
- //Returns advanced debug information type
- advanced_info_type get_advanced_info_type() const;
- //Returns advanced debug information or throws an exception,
- //if requested information type is not contained by structure
- template<typename AdvancedInfo>
- const AdvancedInfo get_advanced_debug_info() const;
-
-public: //These functions do not change everything inside image, they are used by PE class
- //Sets advanced debug information
- void set_advanced_debug_info(const pdb_7_0_info& info);
- void set_advanced_debug_info(const pdb_2_0_info& info);
- void set_advanced_debug_info(const misc_debug_info& info);
- void set_advanced_debug_info(const coff_debug_info& info);
-
- //Sets advanced debug information type, if no advanced info structure available
- void set_advanced_info_type(advanced_info_type type);
-
-private:
- uint32_t characteristics_;
- uint32_t time_stamp_;
- uint32_t major_version_, minor_version_;
- uint32_t type_;
- uint32_t size_of_data_;
- uint32_t address_of_raw_data_; //RVA when mapped or 0
- uint32_t pointer_to_raw_data_; //RAW file offset
-
- //Union containing advanced debug information pointer
- union advanced_info
- {
- public:
- //Default constructor
- advanced_info();
-
- //Returns true if advanced debug info is present
- bool is_present() const;
-
- public:
- pdb_7_0_info* adv_pdb_7_0_info;
- pdb_2_0_info* adv_pdb_2_0_info;
- misc_debug_info* adv_misc_info;
- coff_debug_info* adv_coff_info;
- };
-
- //Helper for advanced debug information copying
- void copy_advanced_info(const debug_info& info);
- //Helper for clearing any present advanced debug information
- void free_present_advanced_info();
-
- advanced_info advanced_debug_info_;
- //Advanced information type
- advanced_info_type advanced_info_type_;
-};
-
-typedef std::vector<debug_info> debug_info_list;
-
-//Returns debug information list
-const debug_info_list get_debug_information(const pe_base& pe);
-}
diff --git a/tools/pe_bliss/pe_directory.cpp b/tools/pe_bliss/pe_directory.cpp
deleted file mode 100644
index 13ad2afc5d..0000000000
--- a/tools/pe_bliss/pe_directory.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_directory.h"
-
-namespace pe_bliss
-{
-//Default constructor
-image_directory::image_directory()
- :rva_(0), size_(0)
-{}
-
-//Constructor from data
-image_directory::image_directory(uint32_t rva, uint32_t size)
- :rva_(rva), size_(size)
-{}
-
-//Returns RVA
-uint32_t image_directory::get_rva() const
-{
- return rva_;
-}
-
-//Returns size
-uint32_t image_directory::get_size() const
-{
- return size_;
-}
-
-//Sets RVA
-void image_directory::set_rva(uint32_t rva)
-{
- rva_ = rva;
-}
-
-//Sets size
-void image_directory::set_size(uint32_t size)
-{
- size_ = size;
-}
-}
diff --git a/tools/pe_bliss/pe_directory.h b/tools/pe_bliss/pe_directory.h
deleted file mode 100644
index a7b1ea7a5f..0000000000
--- a/tools/pe_bliss/pe_directory.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-//Class representing image directory data
-class image_directory
-{
-public:
- //Default constructor
- image_directory();
- //Constructor from data
- image_directory(uint32_t rva, uint32_t size);
-
- //Returns RVA
- uint32_t get_rva() const;
- //Returns size
- uint32_t get_size() const;
-
- //Sets RVA
- void set_rva(uint32_t rva);
- //Sets size
- void set_size(uint32_t size);
-
-private:
- uint32_t rva_;
- uint32_t size_;
-};
-}
diff --git a/tools/pe_bliss/pe_dotnet.cpp b/tools/pe_bliss/pe_dotnet.cpp
deleted file mode 100644
index f34a76eae8..0000000000
--- a/tools/pe_bliss/pe_dotnet.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "pe_dotnet.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//.NET
-basic_dotnet_info::basic_dotnet_info()
-{
- memset(&header_, 0, sizeof(header_));
-}
-
-//Constructor from data
-basic_dotnet_info::basic_dotnet_info(const image_cor20_header& header)
- :header_(header)
-{}
-
-//Returns major runtime version
-uint16_t basic_dotnet_info::get_major_runtime_version() const
-{
- return header_.MajorRuntimeVersion;
-}
-
-//Returns minor runtime version
-uint16_t basic_dotnet_info::get_minor_runtime_version() const
-{
- return header_.MinorRuntimeVersion;
-}
-
-//Returns RVA of metadata (symbol table and startup information)
-uint32_t basic_dotnet_info::get_rva_of_metadata() const
-{
- return header_.MetaData.VirtualAddress;
-}
-
-//Returns size of metadata (symbol table and startup information)
-uint32_t basic_dotnet_info::get_size_of_metadata() const
-{
- return header_.MetaData.Size;
-}
-
-//Returns flags
-uint32_t basic_dotnet_info::get_flags() const
-{
- return header_.Flags;
-}
-
-//Returns true if entry point is native
-bool basic_dotnet_info::is_native_entry_point() const
-{
- return (header_.Flags & comimage_flags_native_entrypoint) ? true : false;
-}
-
-//Returns true if 32 bit required
-bool basic_dotnet_info::is_32bit_required() const
-{
- return (header_.Flags & comimage_flags_32bitrequired) ? true : false;
-}
-
-//Returns true if image is IL library
-bool basic_dotnet_info::is_il_library() const
-{
- return (header_.Flags & comimage_flags_il_library) ? true : false;
-}
-
-//Returns true if image uses IL only
-bool basic_dotnet_info::is_il_only() const
-{
- return (header_.Flags & comimage_flags_ilonly) ? true : false;
-}
-
-//Returns entry point RVA (if entry point is native)
-//Returns entry point managed token (if entry point is managed)
-uint32_t basic_dotnet_info::get_entry_point_rva_or_token() const
-{
- return header_.EntryPointToken;
-}
-
-//Returns RVA of managed resources
-uint32_t basic_dotnet_info::get_rva_of_resources() const
-{
- return header_.Resources.VirtualAddress;
-}
-
-//Returns size of managed resources
-uint32_t basic_dotnet_info::get_size_of_resources() const
-{
- return header_.Resources.Size;
-}
-
-//Returns RVA of strong name signature
-uint32_t basic_dotnet_info::get_rva_of_strong_name_signature() const
-{
- return header_.StrongNameSignature.VirtualAddress;
-}
-
-//Returns size of strong name signature
-uint32_t basic_dotnet_info::get_size_of_strong_name_signature() const
-{
- return header_.StrongNameSignature.Size;
-}
-
-//Returns RVA of code manager table
-uint32_t basic_dotnet_info::get_rva_of_code_manager_table() const
-{
- return header_.CodeManagerTable.VirtualAddress;
-}
-
-//Returns size of code manager table
-uint32_t basic_dotnet_info::get_size_of_code_manager_table() const
-{
- return header_.CodeManagerTable.Size;
-}
-
-//Returns RVA of VTable fixups
-uint32_t basic_dotnet_info::get_rva_of_vtable_fixups() const
-{
- return header_.VTableFixups.VirtualAddress;
-}
-
-//Returns size of VTable fixups
-uint32_t basic_dotnet_info::get_size_of_vtable_fixups() const
-{
- return header_.VTableFixups.Size;
-}
-
-//Returns RVA of export address table jumps
-uint32_t basic_dotnet_info::get_rva_of_export_address_table_jumps() const
-{
- return header_.ExportAddressTableJumps.VirtualAddress;
-}
-
-//Returns size of export address table jumps
-uint32_t basic_dotnet_info::get_size_of_export_address_table_jumps() const
-{
- return header_.ExportAddressTableJumps.Size;
-}
-
-//Returns RVA of managed native header
-//(precompiled header info, usually set to zero, for internal use)
-uint32_t basic_dotnet_info::get_rva_of_managed_native_header() const
-{
- return header_.ManagedNativeHeader.VirtualAddress;
-}
-
-//Returns size of managed native header
-//(precompiled header info, usually set to zero, for internal use)
-uint32_t basic_dotnet_info::get_size_of_managed_native_header() const
-{
- return header_.ManagedNativeHeader.Size;
-}
-
-//Returns basic .NET information
-//If image is not native, throws an exception
-const basic_dotnet_info get_basic_dotnet_info(const pe_base& pe)
-{
- //If there's no debug directory, return empty list
- if(!pe.is_dotnet())
- throw pe_exception("Image does not have managed code", pe_exception::image_does_not_have_managed_code);
-
- //Return basic .NET information
- return basic_dotnet_info(pe.section_data_from_rva<image_cor20_header>(pe.get_directory_rva(image_directory_entry_com_descriptor), section_data_virtual, true));
-}
-}
diff --git a/tools/pe_bliss/pe_dotnet.h b/tools/pe_bliss/pe_dotnet.h
deleted file mode 100644
index 96b0ac7d0a..0000000000
--- a/tools/pe_bliss/pe_dotnet.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include "pe_structures.h"
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-//Class representing basic .NET header information
-class basic_dotnet_info
-{
-public:
- //Default constructor
- basic_dotnet_info();
- //Constructor from data
- explicit basic_dotnet_info(const pe_win::image_cor20_header& header);
-
- //Returns major runtime version
- uint16_t get_major_runtime_version() const;
- //Returns minor runtime version
- uint16_t get_minor_runtime_version() const;
-
- //Returns RVA of metadata (symbol table and startup information)
- uint32_t get_rva_of_metadata() const;
- //Returns size of metadata (symbol table and startup information)
- uint32_t get_size_of_metadata() const;
-
- //Returns flags
- uint32_t get_flags() const;
-
- //Returns true if entry point is native
- bool is_native_entry_point() const;
- //Returns true if 32 bit required
- bool is_32bit_required() const;
- //Returns true if image is IL library
- bool is_il_library() const;
- //Returns true if image uses IL only
- bool is_il_only() const;
-
- //Returns entry point RVA (if entry point is native)
- //Returns entry point managed token (if entry point is managed)
- uint32_t get_entry_point_rva_or_token() const;
-
- //Returns RVA of managed resources
- uint32_t get_rva_of_resources() const;
- //Returns size of managed resources
- uint32_t get_size_of_resources() const;
- //Returns RVA of strong name signature
- uint32_t get_rva_of_strong_name_signature() const;
- //Returns size of strong name signature
- uint32_t get_size_of_strong_name_signature() const;
- //Returns RVA of code manager table
- uint32_t get_rva_of_code_manager_table() const;
- //Returns size of code manager table
- uint32_t get_size_of_code_manager_table() const;
- //Returns RVA of VTable fixups
- uint32_t get_rva_of_vtable_fixups() const;
- //Returns size of VTable fixups
- uint32_t get_size_of_vtable_fixups() const;
- //Returns RVA of export address table jumps
- uint32_t get_rva_of_export_address_table_jumps() const;
- //Returns size of export address table jumps
- uint32_t get_size_of_export_address_table_jumps() const;
- //Returns RVA of managed native header
- //(precompiled header info, usually set to zero, for internal use)
- uint32_t get_rva_of_managed_native_header() const;
- //Returns size of managed native header
- //(precompiled header info, usually set to zero, for internal use)
- uint32_t get_size_of_managed_native_header() const;
-
-private:
- pe_win::image_cor20_header header_;
-};
-
-//Returns basic .NET information
-//If image is not native, throws an exception
-const basic_dotnet_info get_basic_dotnet_info(const pe_base& pe);
-}
diff --git a/tools/pe_bliss/pe_exception.cpp b/tools/pe_bliss/pe_exception.cpp
deleted file mode 100644
index 3161f93599..0000000000
--- a/tools/pe_bliss/pe_exception.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_exception.h"
-
-namespace pe_bliss
-{
-//PE exception class constructors
-pe_exception::pe_exception(const char* text, exception_id id)
- :std::runtime_error(text), id_(id)
-{}
-
-pe_exception::pe_exception(const std::string& text, exception_id id)
- :std::runtime_error(text), id_(id)
-{}
-
-//Returns exception ID
-pe_exception::exception_id pe_exception::get_id() const
-{
- return id_;
-}
-}
diff --git a/tools/pe_bliss/pe_exception.h b/tools/pe_bliss/pe_exception.h
deleted file mode 100644
index 2b58a95772..0000000000
--- a/tools/pe_bliss/pe_exception.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <exception>
-#include <stdexcept>
-
-namespace pe_bliss
-{
-//PE exception class
-class pe_exception : public std::runtime_error
-{
-public:
- //Exception IDs
- enum exception_id
- {
- unknown_error,
- bad_pe_file,
- bad_dos_header,
- image_nt_headers_not_found,
- error_reading_image_nt_headers,
- error_reading_data_directories,
- error_reading_file,
- pe_signature_incorrect,
- incorrect_number_of_rva_and_sizes,
- error_changing_section_virtual_size,
- section_number_incorrect,
- section_table_incorrect,
- incorrect_section_alignment,
- incorrect_file_alignment,
- incorrect_size_of_image,
- incorrect_size_of_headers,
- image_section_headers_not_found,
- zero_section_sizes,
- section_incorrect_addr_or_size,
- section_not_found,
- image_section_data_not_found,
- no_section_found,
- image_section_table_incorrect,
- directory_does_not_exist,
- rva_not_exists,
- error_reading_section_header,
- error_reading_overlay,
- incorrect_address_conversion,
-
- incorrect_export_directory,
- incorrect_import_directory,
- incorrect_relocation_directory,
- incorrect_tls_directory,
- incorrect_config_directory,
- incorrect_bound_import_directory,
- incorrect_resource_directory,
- incorrect_exception_directory,
- incorrect_debug_directory,
-
- resource_directory_entry_error,
- resource_directory_entry_not_found,
- resource_data_entry_not_found,
- resource_incorrect_bitmap,
- resource_incorrect_icon,
- resource_incorrect_cursor,
- resource_incorrect_string_table,
- resource_string_not_found,
- resource_incorrect_message_table,
- resource_incorrect_version_info,
-
- advanced_debug_information_request_error,
- image_does_not_have_managed_code,
-
- section_is_empty,
- data_is_empty,
- stream_is_bad,
-
- section_is_not_attached,
- insufficient_space,
-
- cannot_rebase_relocations,
-
- exports_list_is_empty,
- duplicate_exported_function_ordinal,
- duplicate_exported_function_name,
-
- version_info_string_does_not_exist,
-
- no_more_sections_can_be_added,
-
- no_icon_group_found,
- no_cursor_group_found,
-
- encoding_convertion_error,
-
- error_expanding_section,
-
- cannot_rebuild_image
- };
-
-public:
- //Class constructors
- explicit pe_exception(const char* text, exception_id id = unknown_error);
- explicit pe_exception(const std::string& text, exception_id id = unknown_error);
-
- //Returns exception ID from exception_id enumeration
- exception_id get_id() const;
-
- //Destructor
- virtual ~pe_exception() throw()
- {}
-
-private:
- exception_id id_;
-};
-}
diff --git a/tools/pe_bliss/pe_exception_directory.cpp b/tools/pe_bliss/pe_exception_directory.cpp
deleted file mode 100644
index 1813f02021..0000000000
--- a/tools/pe_bliss/pe_exception_directory.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_exception_directory.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//EXCEPTION DIRECTORY (exists on PE+ only)
-//Default constructor
-exception_entry::exception_entry()
- :begin_address_(0), end_address_(0), unwind_info_address_(0),
- unwind_info_version_(0),
- flags_(0),
- size_of_prolog_(0),
- count_of_codes_(0),
- frame_register_(0),
- frame_offset_(0)
-{}
-
-//Constructor from data
-exception_entry::exception_entry(const image_runtime_function_entry& entry, const unwind_info& unwind_info)
- :begin_address_(entry.BeginAddress), end_address_(entry.EndAddress), unwind_info_address_(entry.UnwindInfoAddress),
- unwind_info_version_(unwind_info.Version),
- flags_(unwind_info.Flags),
- size_of_prolog_(unwind_info.SizeOfProlog),
- count_of_codes_(unwind_info.CountOfCodes),
- frame_register_(unwind_info.FrameRegister),
- frame_offset_(unwind_info.FrameOffset)
-{}
-
-//Returns starting address of function, affected by exception unwinding
-uint32_t exception_entry::get_begin_address() const
-{
- return begin_address_;
-}
-
-//Returns ending address of function, affected by exception unwinding
-uint32_t exception_entry::get_end_address() const
-{
- return end_address_;
-}
-
-//Returns unwind info address
-uint32_t exception_entry::get_unwind_info_address() const
-{
- return unwind_info_address_;
-}
-
-//Returns UNWIND_INFO structure version
-uint8_t exception_entry::get_unwind_info_version() const
-{
- return unwind_info_version_;
-}
-
-//Returns unwind info flags
-uint8_t exception_entry::get_flags() const
-{
- return flags_;
-}
-
-//The function has an exception handler that should be called
-//when looking for functions that need to examine exceptions
-bool exception_entry::has_exception_handler() const
-{
- return (flags_ & unw_flag_ehandler) ? true : false;
-}
-
-//The function has a termination handler that should be called
-//when unwinding an exception
-bool exception_entry::has_termination_handler() const
-{
- return (flags_ & unw_flag_uhandler) ? true : false;
-}
-
-//The unwind info structure is not the primary one for the procedure
-bool exception_entry::is_chaininfo() const
-{
- return (flags_ & unw_flag_chaininfo) ? true : false;
-}
-
-//Returns size of function prolog
-uint8_t exception_entry::get_size_of_prolog() const
-{
- return size_of_prolog_;
-}
-
-//Returns number of unwind slots
-uint8_t exception_entry::get_number_of_unwind_slots() const
-{
- return count_of_codes_;
-}
-
-//If the function uses frame pointer
-bool exception_entry::uses_frame_pointer() const
-{
- return frame_register_ != 0;
-}
-
-//Number of the nonvolatile register used as the frame pointer,
-//using the same encoding for the operation info field of UNWIND_CODE nodes
-uint8_t exception_entry::get_frame_pointer_register_number() const
-{
- return frame_register_;
-}
-
-//The scaled offset from RSP that is applied to the FP reg when it is established.
-//The actual FP reg is set to RSP + 16 * this number, allowing offsets from 0 to 240
-uint8_t exception_entry::get_scaled_rsp_offset() const
-{
- return frame_offset_;
-}
-
-//Returns exception directory data (exists on PE+ only)
-//Unwind opcodes are not listed, because their format and list are subject to change
-const exception_entry_list get_exception_directory_data(const pe_base& pe)
-{
- exception_entry_list ret;
-
- //If image doesn't have exception directory, return empty list
- if(!pe.has_exception_directory())
- return ret;
-
- //Check the length in bytes of the section containing exception directory
- if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_exception), pe.get_directory_rva(image_directory_entry_exception), section_data_virtual, true)
- < sizeof(image_runtime_function_entry))
- throw pe_exception("Incorrect exception directory", pe_exception::incorrect_exception_directory);
-
- unsigned long current_pos = pe.get_directory_rva(image_directory_entry_exception);
-
- //Check if structures are DWORD-aligned
- if(current_pos % sizeof(uint32_t))
- throw pe_exception("Incorrect exception directory", pe_exception::incorrect_exception_directory);
-
- //First IMAGE_RUNTIME_FUNCTION_ENTRY table
- image_runtime_function_entry exception_table = pe.section_data_from_rva<image_runtime_function_entry>(current_pos, section_data_virtual, true);
-
- //todo: virtual addresses BeginAddress and EndAddress are not checked to be inside image
- while(exception_table.BeginAddress)
- {
- //Check addresses
- if(exception_table.BeginAddress > exception_table.EndAddress)
- throw pe_exception("Incorrect exception directory", pe_exception::incorrect_exception_directory);
-
- //Get unwind information
- unwind_info info = pe.section_data_from_rva<unwind_info>(exception_table.UnwindInfoAddress, section_data_virtual, true);
-
- //Create exception entry and save it
- ret.push_back(exception_entry(exception_table, info));
-
- //Go to next exception entry
- current_pos += sizeof(image_runtime_function_entry);
- exception_table = pe.section_data_from_rva<image_runtime_function_entry>(current_pos, section_data_virtual, true);
- }
-
- return ret;
-}
-}
diff --git a/tools/pe_bliss/pe_exception_directory.h b/tools/pe_bliss/pe_exception_directory.h
deleted file mode 100644
index 6f4fc2298b..0000000000
--- a/tools/pe_bliss/pe_exception_directory.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include "pe_structures.h"
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-//Class representing exception directory entry
-class exception_entry
-{
-public:
- //Default constructor
- exception_entry();
- //Constructor from data
- exception_entry(const pe_win::image_runtime_function_entry& entry, const pe_win::unwind_info& unwind_info);
-
- //Returns starting address of function, affected by exception unwinding
- uint32_t get_begin_address() const;
- //Returns ending address of function, affected by exception unwinding
- uint32_t get_end_address() const;
- //Returns unwind info address
- uint32_t get_unwind_info_address() const;
-
- //Returns UNWIND_INFO structure version
- uint8_t get_unwind_info_version() const;
-
- //Returns unwind info flags
- uint8_t get_flags() const;
- //The function has an exception handler that should be called
- //when looking for functions that need to examine exceptions
- bool has_exception_handler() const;
- //The function has a termination handler that should be called
- //when unwinding an exception
- bool has_termination_handler() const;
- //The unwind info structure is not the primary one for the procedure
- bool is_chaininfo() const;
-
- //Returns size of function prolog
- uint8_t get_size_of_prolog() const;
-
- //Returns number of unwind slots
- uint8_t get_number_of_unwind_slots() const;
-
- //If the function uses frame pointer
- bool uses_frame_pointer() const;
- //Number of the nonvolatile register used as the frame pointer,
- //using the same encoding for the operation info field of UNWIND_CODE nodes
- uint8_t get_frame_pointer_register_number() const;
- //The scaled offset from RSP that is applied to the FP reg when it is established.
- //The actual FP reg is set to RSP + 16 * this number, allowing offsets from 0 to 240
- uint8_t get_scaled_rsp_offset() const;
-
-private:
- uint32_t begin_address_, end_address_, unwind_info_address_;
- uint8_t unwind_info_version_;
- uint8_t flags_;
- uint8_t size_of_prolog_;
- uint8_t count_of_codes_;
- uint8_t frame_register_, frame_offset_;
-};
-
-typedef std::vector<exception_entry> exception_entry_list;
-
-//Returns exception directory data (exists on PE+ only)
-//Unwind opcodes are not listed, because their format and list are subject to change
-const exception_entry_list get_exception_directory_data(const pe_base& pe);
-}
diff --git a/tools/pe_bliss/pe_exports.cpp b/tools/pe_bliss/pe_exports.cpp
deleted file mode 100644
index c2ad895554..0000000000
--- a/tools/pe_bliss/pe_exports.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <set>
-#include <algorithm>
-#include <string.h>
-#include "pe_exports.h"
-#include "utils.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//EXPORTS
-//Default constructor
-exported_function::exported_function()
- :ordinal_(0), rva_(0), has_name_(false), name_ordinal_(0), forward_(false)
-{}
-
-//Returns ordinal of function (actually, ordinal = hint + ordinal base)
-uint16_t exported_function::get_ordinal() const
-{
- return ordinal_;
-}
-
-//Returns RVA of function
-uint32_t exported_function::get_rva() const
-{
- return rva_;
-}
-
-//Returns name of function
-const std::string& exported_function::get_name() const
-{
- return name_;
-}
-
-//Returns true if function has name and name ordinal
-bool exported_function::has_name() const
-{
- return has_name_;
-}
-
-//Returns name ordinal of function
-uint16_t exported_function::get_name_ordinal() const
-{
- return name_ordinal_;
-}
-
-//Returns true if function is forwarded to other library
-bool exported_function::is_forwarded() const
-{
- return forward_;
-}
-
-//Returns the name of forwarded function
-const std::string& exported_function::get_forwarded_name() const
-{
- return forward_name_;
-}
-
-//Sets ordinal of function
-void exported_function::set_ordinal(uint16_t ordinal)
-{
- ordinal_ = ordinal;
-}
-
-//Sets RVA of function
-void exported_function::set_rva(uint32_t rva)
-{
- rva_ = rva;
-}
-
-//Sets name of function (or clears it, if empty name is passed)
-void exported_function::set_name(const std::string& name)
-{
- name_ = name;
- has_name_ = !name.empty();
-}
-
-//Sets name ordinal
-void exported_function::set_name_ordinal(uint16_t name_ordinal)
-{
- name_ordinal_ = name_ordinal;
-}
-
-//Sets forwarded function name (or clears it, if empty name is passed)
-void exported_function::set_forwarded_name(const std::string& name)
-{
- forward_name_ = name;
- forward_ = !name.empty();
-}
-
-//Default constructor
-export_info::export_info()
- :characteristics_(0),
- timestamp_(0),
- major_version_(0),
- minor_version_(0),
- ordinal_base_(0),
- number_of_functions_(0),
- number_of_names_(0),
- address_of_functions_(0),
- address_of_names_(0),
- address_of_name_ordinals_(0)
-{}
-
-//Returns characteristics
-uint32_t export_info::get_characteristics() const
-{
- return characteristics_;
-}
-
-//Returns timestamp
-uint32_t export_info::get_timestamp() const
-{
- return timestamp_;
-}
-
-//Returns major version
-uint16_t export_info::get_major_version() const
-{
- return major_version_;
-}
-
-//Returns minor version
-uint16_t export_info::get_minor_version() const
-{
- return minor_version_;
-}
-
-//Returns DLL name
-const std::string& export_info::get_name() const
-{
- return name_;
-}
-
-//Returns ordinal base
-uint32_t export_info::get_ordinal_base() const
-{
- return ordinal_base_;
-}
-
-//Returns number of functions
-uint32_t export_info::get_number_of_functions() const
-{
- return number_of_functions_;
-}
-
-//Returns number of function names
-uint32_t export_info::get_number_of_names() const
-{
- return number_of_names_;
-}
-
-//Returns RVA of function address table
-uint32_t export_info::get_rva_of_functions() const
-{
- return address_of_functions_;
-}
-
-//Returns RVA of function name address table
-uint32_t export_info::get_rva_of_names() const
-{
- return address_of_names_;
-}
-
-//Returns RVA of name ordinals table
-uint32_t export_info::get_rva_of_name_ordinals() const
-{
- return address_of_name_ordinals_;
-}
-
-//Sets characteristics
-void export_info::set_characteristics(uint32_t characteristics)
-{
- characteristics_ = characteristics;
-}
-
-//Sets timestamp
-void export_info::set_timestamp(uint32_t timestamp)
-{
- timestamp_ = timestamp;
-}
-
-//Sets major version
-void export_info::set_major_version(uint16_t major_version)
-{
- major_version_ = major_version;
-}
-
-//Sets minor version
-void export_info::set_minor_version(uint16_t minor_version)
-{
- minor_version_ = minor_version;
-}
-
-//Sets DLL name
-void export_info::set_name(const std::string& name)
-{
- name_ = name;
-}
-
-//Sets ordinal base
-void export_info::set_ordinal_base(uint32_t ordinal_base)
-{
- ordinal_base_ = ordinal_base;
-}
-
-//Sets number of functions
-void export_info::set_number_of_functions(uint32_t number_of_functions)
-{
- number_of_functions_ = number_of_functions;
-}
-
-//Sets number of function names
-void export_info::set_number_of_names(uint32_t number_of_names)
-{
- number_of_names_ = number_of_names;
-}
-
-//Sets RVA of function address table
-void export_info::set_rva_of_functions(uint32_t rva_of_functions)
-{
- address_of_functions_ = rva_of_functions;
-}
-
-//Sets RVA of function name address table
-void export_info::set_rva_of_names(uint32_t rva_of_names)
-{
- address_of_names_ = rva_of_names;
-}
-
-//Sets RVA of name ordinals table
-void export_info::set_rva_of_name_ordinals(uint32_t rva_of_name_ordinals)
-{
- address_of_name_ordinals_ = rva_of_name_ordinals;
-}
-
-const exported_functions_list get_exported_functions(const pe_base& pe, export_info* info);
-
-//Returns array of exported functions
-const exported_functions_list get_exported_functions(const pe_base& pe)
-{
- return get_exported_functions(pe, 0);
-}
-
-//Returns array of exported functions and information about export
-const exported_functions_list get_exported_functions(const pe_base& pe, export_info& info)
-{
- return get_exported_functions(pe, &info);
-}
-
-//Helper: sorts exported function list by ordinals
-struct ordinal_sorter
-{
-public:
- bool operator()(const exported_function& func1, const exported_function& func2) const;
-};
-
-//Returns array of exported functions and information about export (if info != 0)
-const exported_functions_list get_exported_functions(const pe_base& pe, export_info* info)
-{
- //Returned exported functions info array
- std::vector<exported_function> ret;
-
- if(pe.has_exports())
- {
- //Check the length in bytes of the section containing export directory
- if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_export),
- pe.get_directory_rva(image_directory_entry_export), section_data_virtual, true)
- < sizeof(image_export_directory))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- image_export_directory exports = pe.section_data_from_rva<image_export_directory>(pe.get_directory_rva(image_directory_entry_export), section_data_virtual, true);
-
- unsigned long max_name_length;
-
- if(info)
- {
- //Save some export info data
- info->set_characteristics(exports.Characteristics);
- info->set_major_version(exports.MajorVersion);
- info->set_minor_version(exports.MinorVersion);
-
- //Get byte count that we have for dll name
- if((max_name_length = pe.section_data_length_from_rva(exports.Name, exports.Name, section_data_virtual, true)) < 2)
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Get dll name pointer
- const char* dll_name = pe.section_data_from_rva(exports.Name, section_data_virtual, true);
-
- //Check for null-termination
- if(!pe_utils::is_null_terminated(dll_name, max_name_length))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Save the rest of export information data
- info->set_name(dll_name);
- info->set_number_of_functions(exports.NumberOfFunctions);
- info->set_number_of_names(exports.NumberOfNames);
- info->set_ordinal_base(exports.Base);
- info->set_rva_of_functions(exports.AddressOfFunctions);
- info->set_rva_of_names(exports.AddressOfNames);
- info->set_rva_of_name_ordinals(exports.AddressOfNameOrdinals);
- info->set_timestamp(exports.TimeDateStamp);
- }
-
- if(!exports.NumberOfFunctions)
- return ret;
-
- //Check IMAGE_EXPORT_DIRECTORY fields
- if(exports.NumberOfNames > exports.NumberOfFunctions)
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Check some export directory fields
- if((!exports.AddressOfNameOrdinals && exports.AddressOfNames) ||
- (exports.AddressOfNameOrdinals && !exports.AddressOfNames) ||
- !exports.AddressOfFunctions
- || exports.NumberOfFunctions >= pe_utils::max_dword / sizeof(uint32_t)
- || exports.NumberOfNames > pe_utils::max_dword / sizeof(uint32_t)
- || !pe_utils::is_sum_safe(exports.AddressOfFunctions, exports.NumberOfFunctions * sizeof(uint32_t))
- || !pe_utils::is_sum_safe(exports.AddressOfNames, exports.NumberOfNames * sizeof(uint32_t))
- || !pe_utils::is_sum_safe(exports.AddressOfNameOrdinals, exports.NumberOfFunctions * sizeof(uint32_t))
- || !pe_utils::is_sum_safe(pe.get_directory_rva(image_directory_entry_export), pe.get_directory_size(image_directory_entry_export)))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Check if it is enough bytes to hold AddressOfFunctions table
- if(pe.section_data_length_from_rva(exports.AddressOfFunctions, exports.AddressOfFunctions, section_data_virtual, true)
- < exports.NumberOfFunctions * sizeof(uint32_t))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- if(exports.AddressOfNames)
- {
- //Check if it is enough bytes to hold name and ordinal tables
- if(pe.section_data_length_from_rva(exports.AddressOfNameOrdinals, exports.AddressOfNameOrdinals, section_data_virtual, true)
- < exports.NumberOfNames * sizeof(uint16_t))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- if(pe.section_data_length_from_rva(exports.AddressOfNames, exports.AddressOfNames, section_data_virtual, true)
- < exports.NumberOfNames * sizeof(uint32_t))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
- }
-
- for(uint32_t ordinal = 0; ordinal < exports.NumberOfFunctions; ordinal++)
- {
- //Get function address
- //Sum and multiplication are safe (checked above)
- uint32_t rva = pe.section_data_from_rva<uint32_t>(exports.AddressOfFunctions + ordinal * sizeof(uint32_t), section_data_virtual, true);
-
- //If we have a skip
- if(!rva)
- continue;
-
- exported_function func;
- func.set_rva(rva);
-
- if(!pe_utils::is_sum_safe(exports.Base, ordinal) || exports.Base + ordinal > pe_utils::max_word)
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- func.set_ordinal(static_cast<uint16_t>(ordinal + exports.Base));
-
- //Scan for function name ordinal
- for(uint32_t i = 0; i < exports.NumberOfNames; i++)
- {
- uint16_t ordinal2 = pe.section_data_from_rva<uint16_t>(exports.AddressOfNameOrdinals + i * sizeof(uint16_t), section_data_virtual, true);
-
- //If function has name (and name ordinal)
- if(ordinal == ordinal2)
- {
- //Get function name
- //Sum and multiplication are safe (checked above)
- uint32_t function_name_rva = pe.section_data_from_rva<uint32_t>(exports.AddressOfNames + i * sizeof(uint32_t), section_data_virtual, true);
-
- //Get byte count that we have for function name
- if((max_name_length = pe.section_data_length_from_rva(function_name_rva, function_name_rva, section_data_virtual, true)) < 2)
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Get function name pointer
- const char* func_name = pe.section_data_from_rva(function_name_rva, section_data_virtual, true);
-
- //Check for null-termination
- if(!pe_utils::is_null_terminated(func_name, max_name_length))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Save function info
- func.set_name(func_name);
- func.set_name_ordinal(ordinal2);
-
- //If the function is just a redirect, save its name
- if(rva >= pe.get_directory_rva(image_directory_entry_export) + sizeof(image_directory_entry_export) &&
- rva < pe.get_directory_rva(image_directory_entry_export) + pe.get_directory_size(image_directory_entry_export))
- {
- if((max_name_length = pe.section_data_length_from_rva(rva, rva, section_data_virtual, true)) < 2)
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Get forwarded function name pointer
- const char* forwarded_func_name = pe.section_data_from_rva(rva, section_data_virtual, true);
-
- //Check for null-termination
- if(!pe_utils::is_null_terminated(forwarded_func_name, max_name_length))
- throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
-
- //Set the name of forwarded function
- func.set_forwarded_name(forwarded_func_name);
- }
-
- break;
- }
- }
-
- //Add function info to output array
- ret.push_back(func);
- }
- }
-
- return ret;
-}
-
-//Helper export functions
-//Returns pair: <ordinal base for supplied functions; maximum ordinal value for supplied functions>
-const std::pair<uint16_t, uint16_t> get_export_ordinal_limits(const exported_functions_list& exports)
-{
- if(exports.empty())
- return std::make_pair(0, 0);
-
- uint16_t max_ordinal = 0; //Maximum ordinal number
- uint16_t ordinal_base = pe_utils::max_word; //Minimum ordinal value
- for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it)
- {
- const exported_function& func = (*it);
-
- //Calculate maximum and minimum ordinal numbers
- max_ordinal = std::max<uint16_t>(max_ordinal, func.get_ordinal());
- ordinal_base = std::min<uint16_t>(ordinal_base, func.get_ordinal());
- }
-
- return std::make_pair(ordinal_base, max_ordinal);
-}
-
-//Checks if exported function name already exists
-bool exported_name_exists(const std::string& function_name, const exported_functions_list& exports)
-{
- for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it)
- {
- if((*it).has_name() && (*it).get_name() == function_name)
- return true;
- }
-
- return false;
-}
-
-//Checks if exported function name already exists
-bool exported_ordinal_exists(uint16_t ordinal, const exported_functions_list& exports)
-{
- for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it)
- {
- if((*it).get_ordinal() == ordinal)
- return true;
- }
-
- return false;
-}
-
-//Helper: sorts exported function list by ordinals
-bool ordinal_sorter::operator()(const exported_function& func1, const exported_function& func2) const
-{
- return func1.get_ordinal() < func2.get_ordinal();
-}
-
-//Export directory rebuilder
-//info - export information
-//exported_functions_list - list of exported functions
-//exports_section - section where export directory will be placed (must be attached to PE image)
-//offset_from_section_start - offset from exports_section raw data start
-//save_to_pe_headers - if true, new export directory information will be saved to PE image headers
-//auto_strip_last_section - if true and exports are placed in the last section, it will be automatically stripped
-//number_of_functions and number_of_names parameters don't matter in "info" when rebuilding, they're calculated independently
-//characteristics, major_version, minor_version, timestamp and name are the only used members of "info" structure
-//Returns new export directory information
-//exported_functions_list is copied intentionally to be sorted by ordinal values later
-//Name ordinals in exported function don't matter, they will be recalculated
-const image_directory rebuild_exports(pe_base& pe, const export_info& info, exported_functions_list exports, section& exports_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section)
-{
- //Check that exports_section is attached to this PE image
- if(!pe.section_attached(exports_section))
- throw pe_exception("Exports section must be attached to PE file", pe_exception::section_is_not_attached);
-
- //Needed space for strings
- uint32_t needed_size_for_strings = static_cast<uint32_t>(info.get_name().length() + 1);
- uint32_t number_of_names = 0; //Number of named functions
- uint32_t max_ordinal = 0; //Maximum ordinal number
- uint32_t ordinal_base = static_cast<uint32_t>(-1); //Minimum ordinal value
-
- if(exports.empty())
- ordinal_base = info.get_ordinal_base();
-
- uint32_t needed_size_for_function_names = 0; //Needed space for function name strings
- uint32_t needed_size_for_function_forwards = 0; //Needed space for function forwards names
-
- //List all exported functions
- //Calculate needed size for function list
- {
- //Also check that there're no duplicate names and ordinals
- std::set<std::string> used_function_names;
- std::set<uint16_t> used_function_ordinals;
-
- for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it)
- {
- const exported_function& func = (*it);
- //Calculate maximum and minimum ordinal numbers
- max_ordinal = std::max<uint32_t>(max_ordinal, func.get_ordinal());
- ordinal_base = std::min<uint32_t>(ordinal_base, func.get_ordinal());
-
- //Check if ordinal is unique
- if(!used_function_ordinals.insert(func.get_ordinal()).second)
- throw pe_exception("Duplicate exported function ordinal", pe_exception::duplicate_exported_function_ordinal);
-
- if(func.has_name())
- {
- //If function is named
- ++number_of_names;
- needed_size_for_function_names += static_cast<uint32_t>(func.get_name().length() + 1);
-
- //Check if it's name and name ordinal are unique
- if(!used_function_names.insert(func.get_name()).second)
- throw pe_exception("Duplicate exported function name", pe_exception::duplicate_exported_function_name);
- }
-
- //If function is forwarded to another DLL
- if(func.is_forwarded())
- needed_size_for_function_forwards += static_cast<uint32_t>(func.get_forwarded_name().length() + 1);
- }
- }
-
- //Sort functions by ordinal value
- std::sort(exports.begin(), exports.end(), ordinal_sorter());
-
- //Calculate needed space for different things...
- needed_size_for_strings += needed_size_for_function_names;
- needed_size_for_strings += needed_size_for_function_forwards;
- uint32_t needed_size_for_function_name_ordinals = number_of_names * sizeof(uint16_t);
- uint32_t needed_size_for_function_name_rvas = number_of_names * sizeof(uint32_t);
- uint32_t needed_size_for_function_addresses = (max_ordinal - ordinal_base + 1) * sizeof(uint32_t);
-
- //Export directory header will be placed first
- uint32_t directory_pos = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t));
-
- uint32_t needed_size = sizeof(image_export_directory); //Calculate needed size for export tables and strings
- //sizeof(IMAGE_EXPORT_DIRECTORY) = export directory header
-
- //Total needed space...
- needed_size += needed_size_for_function_name_ordinals; //For list of names ordinals
- needed_size += needed_size_for_function_addresses; //For function RVAs
- needed_size += needed_size_for_strings; //For all strings
- needed_size += needed_size_for_function_name_rvas; //For function name strings RVAs
-
- //Check if exports_section is last one. If it's not, check if there's enough place for exports data
- if(&exports_section != &*(pe.get_image_sections().end() - 1) &&
- (exports_section.empty() || pe_utils::align_up(exports_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + directory_pos))
- throw pe_exception("Insufficient space for export directory", pe_exception::insufficient_space);
-
- std::string& raw_data = exports_section.get_raw_data();
-
- //This will be done only if exports_section is the last section of image or for section with unaligned raw length of data
- if(raw_data.length() < needed_size + directory_pos)
- raw_data.resize(needed_size + directory_pos); //Expand section raw data
-
- //Library name will be placed after it
- uint32_t current_pos_of_function_names = static_cast<uint32_t>(info.get_name().length() + 1 + directory_pos + sizeof(image_export_directory));
- //Next - function names
- uint32_t current_pos_of_function_name_ordinals = current_pos_of_function_names + needed_size_for_function_names;
- //Next - function name ordinals
- uint32_t current_pos_of_function_forwards = current_pos_of_function_name_ordinals + needed_size_for_function_name_ordinals;
- //Finally - function addresses
- uint32_t current_pos_of_function_addresses = current_pos_of_function_forwards + needed_size_for_function_forwards;
- //Next - function names RVAs
- uint32_t current_pos_of_function_names_rvas = current_pos_of_function_addresses + needed_size_for_function_addresses;
-
- {
- //Create export directory and fill it
- image_export_directory dir = {0};
- dir.Characteristics = info.get_characteristics();
- dir.MajorVersion = info.get_major_version();
- dir.MinorVersion = info.get_minor_version();
- dir.TimeDateStamp = info.get_timestamp();
- dir.NumberOfFunctions = max_ordinal - ordinal_base + 1;
- dir.NumberOfNames = number_of_names;
- dir.Base = ordinal_base;
- dir.AddressOfFunctions = pe.rva_from_section_offset(exports_section, current_pos_of_function_addresses);
- dir.AddressOfNameOrdinals = pe.rva_from_section_offset(exports_section, current_pos_of_function_name_ordinals);
- dir.AddressOfNames = pe.rva_from_section_offset(exports_section, current_pos_of_function_names_rvas);
- dir.Name = pe.rva_from_section_offset(exports_section, directory_pos + sizeof(image_export_directory));
-
- //Save it
- memcpy(&raw_data[directory_pos], &dir, sizeof(dir));
- }
-
- //Sve library name
- memcpy(&raw_data[directory_pos + sizeof(image_export_directory)], info.get_name().c_str(), info.get_name().length() + 1);
-
- //A map to sort function names alphabetically
- typedef std::map<std::string, uint16_t> funclist; //function name; function name ordinal
- funclist funcs;
-
- uint32_t last_ordinal = ordinal_base;
- //Enumerate all exported functions
- for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it)
- {
- const exported_function& func = (*it);
-
- //If we're skipping some ordinals...
- if(func.get_ordinal() > last_ordinal)
- {
- //Fill this function RVAs data with zeros
- uint32_t len = sizeof(uint32_t) * (func.get_ordinal() - last_ordinal - 1);
- if(len)
- {
- memset(&raw_data[current_pos_of_function_addresses], 0, len);
- current_pos_of_function_addresses += len;
- }
-
- //Save last encountered ordinal
- last_ordinal = func.get_ordinal();
- }
-
- //If function is named, save its name ordinal and name in sorted alphabetically order
- if(func.has_name())
- funcs.insert(std::make_pair(func.get_name(), static_cast<uint16_t>(func.get_ordinal() - ordinal_base))); //Calculate name ordinal
-
- //If function is forwarded to another DLL
- if(func.is_forwarded())
- {
- //Write its forwarded name and its RVA
- uint32_t function_rva = pe.rva_from_section_offset(exports_section, current_pos_of_function_forwards);
- memcpy(&raw_data[current_pos_of_function_addresses], &function_rva, sizeof(function_rva));
- current_pos_of_function_addresses += sizeof(function_rva);
-
- memcpy(&raw_data[current_pos_of_function_forwards], func.get_forwarded_name().c_str(), func.get_forwarded_name().length() + 1);
- current_pos_of_function_forwards += static_cast<uint32_t>(func.get_forwarded_name().length() + 1);
- }
- else
- {
- //Write actual function RVA
- uint32_t function_rva = func.get_rva();
- memcpy(&raw_data[current_pos_of_function_addresses], &function_rva, sizeof(function_rva));
- current_pos_of_function_addresses += sizeof(function_rva);
- }
- }
-
- //Enumerate sorted function names
- for(funclist::const_iterator it = funcs.begin(); it != funcs.end(); ++it)
- {
- //Save function name RVA
- uint32_t function_name_rva = pe.rva_from_section_offset(exports_section, current_pos_of_function_names);
- memcpy(&raw_data[current_pos_of_function_names_rvas], &function_name_rva, sizeof(function_name_rva));
- current_pos_of_function_names_rvas += sizeof(function_name_rva);
-
- //Save function name
- memcpy(&raw_data[current_pos_of_function_names], (*it).first.c_str(), (*it).first.length() + 1);
- current_pos_of_function_names += static_cast<uint32_t>((*it).first.length() + 1);
-
- //Save function name ordinal
- uint16_t name_ordinal = (*it).second;
- memcpy(&raw_data[current_pos_of_function_name_ordinals], &name_ordinal, sizeof(name_ordinal));
- current_pos_of_function_name_ordinals += sizeof(name_ordinal);
- }
-
- //Adjust section raw and virtual sizes
- pe.recalculate_section_sizes(exports_section, auto_strip_last_section);
-
- image_directory ret(pe.rva_from_section_offset(exports_section, directory_pos), needed_size);
-
- //If auto-rewrite of PE headers is required
- if(save_to_pe_header)
- {
- pe.set_directory_rva(image_directory_entry_export, ret.get_rva());
- pe.set_directory_size(image_directory_entry_export, ret.get_size());
- }
-
- return ret;
-}
-}
diff --git a/tools/pe_bliss/pe_exports.h b/tools/pe_bliss/pe_exports.h
deleted file mode 100644
index 127cf86ed6..0000000000
--- a/tools/pe_bliss/pe_exports.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include <string>
-#include "pe_structures.h"
-#include "pe_base.h"
-#include "pe_directory.h"
-
-namespace pe_bliss
-{
-//Class representing exported function
-class exported_function
-{
-public:
- //Default constructor
- exported_function();
-
- //Returns ordinal of function (actually, ordinal = hint + ordinal base)
- uint16_t get_ordinal() const;
-
- //Returns RVA of function
- uint32_t get_rva() const;
-
- //Returns true if function has name and name ordinal
- bool has_name() const;
- //Returns name of function
- const std::string& get_name() const;
- //Returns name ordinal of function
- uint16_t get_name_ordinal() const;
-
- //Returns true if function is forwarded to other library
- bool is_forwarded() const;
- //Returns the name of forwarded function
- const std::string& get_forwarded_name() const;
-
-public: //Setters do not change everything inside image, they are used by PE class
- //You can also use them to rebuild export directory
-
- //Sets ordinal of function
- void set_ordinal(uint16_t ordinal);
-
- //Sets RVA of function
- void set_rva(uint32_t rva);
-
- //Sets name of function (or clears it, if empty name is passed)
- void set_name(const std::string& name);
- //Sets name ordinal
- void set_name_ordinal(uint16_t name_ordinal);
-
- //Sets forwarded function name (or clears it, if empty name is passed)
- void set_forwarded_name(const std::string& name);
-
-private:
- uint16_t ordinal_; //Function ordinal
- uint32_t rva_; //Function RVA
- std::string name_; //Function name
- bool has_name_; //true == function has name
- uint16_t name_ordinal_; //Function name ordinal
- bool forward_; //true == function is forwarded
- std::string forward_name_; //Name of forwarded function
-};
-
-//Class representing export information
-class export_info
-{
-public:
- //Default constructor
- export_info();
-
- //Returns characteristics
- uint32_t get_characteristics() const;
- //Returns timestamp
- uint32_t get_timestamp() const;
- //Returns major version
- uint16_t get_major_version() const;
- //Returns minor version
- uint16_t get_minor_version() const;
- //Returns DLL name
- const std::string& get_name() const;
- //Returns ordinal base
- uint32_t get_ordinal_base() const;
- //Returns number of functions
- uint32_t get_number_of_functions() const;
- //Returns number of function names
- uint32_t get_number_of_names() const;
- //Returns RVA of function address table
- uint32_t get_rva_of_functions() const;
- //Returns RVA of function name address table
- uint32_t get_rva_of_names() const;
- //Returns RVA of name ordinals table
- uint32_t get_rva_of_name_ordinals() const;
-
-public: //Setters do not change everything inside image, they are used by PE class
- //You can also use them to rebuild export directory using rebuild_exports
-
- //Sets characteristics
- void set_characteristics(uint32_t characteristics);
- //Sets timestamp
- void set_timestamp(uint32_t timestamp);
- //Sets major version
- void set_major_version(uint16_t major_version);
- //Sets minor version
- void set_minor_version(uint16_t minor_version);
- //Sets DLL name
- void set_name(const std::string& name);
- //Sets ordinal base
- void set_ordinal_base(uint32_t ordinal_base);
- //Sets number of functions
- void set_number_of_functions(uint32_t number_of_functions);
- //Sets number of function names
- void set_number_of_names(uint32_t number_of_names);
- //Sets RVA of function address table
- void set_rva_of_functions(uint32_t rva_of_functions);
- //Sets RVA of function name address table
- void set_rva_of_names(uint32_t rva_of_names);
- //Sets RVA of name ordinals table
- void set_rva_of_name_ordinals(uint32_t rva_of_name_ordinals);
-
-private:
- uint32_t characteristics_;
- uint32_t timestamp_;
- uint16_t major_version_;
- uint16_t minor_version_;
- std::string name_;
- uint32_t ordinal_base_;
- uint32_t number_of_functions_;
- uint32_t number_of_names_;
- uint32_t address_of_functions_;
- uint32_t address_of_names_;
- uint32_t address_of_name_ordinals_;
-};
-
-//Exported functions list typedef
-typedef std::vector<exported_function> exported_functions_list;
-
-//Returns array of exported functions
-const exported_functions_list get_exported_functions(const pe_base& pe);
-//Returns array of exported functions and information about export
-const exported_functions_list get_exported_functions(const pe_base& pe, export_info& info);
-
-//Helper export functions
-//Returns pair: <ordinal base for supplied functions; maximum ordinal value for supplied functions>
-const std::pair<uint16_t, uint16_t> get_export_ordinal_limits(const exported_functions_list& exports);
-
-//Checks if exported function name already exists
-bool exported_name_exists(const std::string& function_name, const exported_functions_list& exports);
-
-//Checks if exported function ordinal already exists
-bool exported_ordinal_exists(uint16_t ordinal, const exported_functions_list& exports);
-
-//Export directory rebuilder
-//info - export information
-//exported_functions_list - list of exported functions
-//exports_section - section where export directory will be placed (must be attached to PE image)
-//offset_from_section_start - offset from exports_section raw data start
-//save_to_pe_headers - if true, new export directory information will be saved to PE image headers
-//auto_strip_last_section - if true and exports are placed in the last section, it will be automatically stripped
-//number_of_functions and number_of_names parameters don't matter in "info" when rebuilding, they're calculated independently
-//characteristics, major_version, minor_version, timestamp and name are the only used members of "info" structure
-//Returns new export directory information
-//exported_functions_list is copied intentionally to be sorted by ordinal values later
-//Name ordinals in exported function don't matter, they will be recalculated
-const image_directory rebuild_exports(pe_base& pe, const export_info& info, exported_functions_list exports, section& exports_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-}
diff --git a/tools/pe_bliss/pe_factory.cpp b/tools/pe_bliss/pe_factory.cpp
deleted file mode 100644
index f6d8a3e1ed..0000000000
--- a/tools/pe_bliss/pe_factory.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_factory.h"
-#include "pe_properties_generic.h"
-
-namespace pe_bliss
-{
-pe_base pe_factory::create_pe(std::istream& file, bool read_debug_raw_data)
-{
- return pe_base::get_pe_type(file) == pe_type_32
- ? pe_base(file, pe_properties_32(), read_debug_raw_data)
- : pe_base(file, pe_properties_64(), read_debug_raw_data);
-}
-
-pe_base pe_factory::create_pe(const char* file_path, bool read_debug_raw_data)
-{
- std::ifstream pe_file(file_path, std::ios::in | std::ios::binary);
- if(!pe_file)
- {
- throw pe_exception("Error in open file.", pe_exception::stream_is_bad);
- }
- return pe_factory::create_pe(pe_file,read_debug_raw_data);
-}
-}
diff --git a/tools/pe_bliss/pe_factory.h b/tools/pe_bliss/pe_factory.h
deleted file mode 100644
index 60b42d9b71..0000000000
--- a/tools/pe_bliss/pe_factory.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <memory>
-#include <istream>
-#include <fstream>
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-class pe_factory
-{
-public:
- //Creates pe_base class instance from PE or PE+ istream
- //If read_bound_import_raw_data, raw bound import data will be read (used to get bound import info)
- //If read_debug_raw_data, raw debug data will be read (used to get image debug info)
- static pe_base create_pe(std::istream& file, bool read_debug_raw_data = true);
- static pe_base create_pe(const char* file_path, bool read_debug_raw_data = true);
-};
-}
diff --git a/tools/pe_bliss/pe_imports.cpp b/tools/pe_bliss/pe_imports.cpp
deleted file mode 100644
index 0a6c01d6c0..0000000000
--- a/tools/pe_bliss/pe_imports.cpp
+++ /dev/null
@@ -1,777 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "pe_imports.h"
-#include "pe_properties_generic.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//IMPORTS
-//Default constructor
-//If set_to_pe_headers = true, IMAGE_DIRECTORY_ENTRY_IMPORT entry will be reset
-//to new value after import rebuilding
-//If auto_zero_directory_entry_iat = true, IMAGE_DIRECTORY_ENTRY_IAT will be set to zero
-//IMAGE_DIRECTORY_ENTRY_IAT is used by loader to temporarily make section, where IMAGE_DIRECTORY_ENTRY_IAT RVA points, writeable
-//to be able to modify IAT thunks
-import_rebuilder_settings::import_rebuilder_settings(bool set_to_pe_headers, bool auto_zero_directory_entry_iat)
- :offset_from_section_start_(0),
- build_original_iat_(true),
- save_iat_and_original_iat_rvas_(true),
- fill_missing_original_iats_(false),
- set_to_pe_headers_(set_to_pe_headers),
- zero_directory_entry_iat_(auto_zero_directory_entry_iat),
- rewrite_iat_and_original_iat_contents_(false),
- auto_strip_last_section_(true)
-{}
-
-//Returns offset from section start where import directory data will be placed
-uint32_t import_rebuilder_settings::get_offset_from_section_start() const
-{
- return offset_from_section_start_;
-}
-
-//Returns true if Original import address table (IAT) will be rebuilt
-bool import_rebuilder_settings::build_original_iat() const
-{
- return build_original_iat_;
-}
-
-//Returns true if Original import address and import address tables will not be rebuilt,
-//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
-bool import_rebuilder_settings::save_iat_and_original_iat_rvas() const
-{
- return save_iat_and_original_iat_rvas_;
-}
-
-//Returns true if Original import address and import address tables contents will be rewritten
-//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
-//and save_iat_and_original_iat_rvas is true
-bool import_rebuilder_settings::rewrite_iat_and_original_iat_contents() const
-{
- return rewrite_iat_and_original_iat_contents_;
-}
-
-//Returns true if original missing IATs will be rebuilt
-//(only if IATs are saved)
-bool import_rebuilder_settings::fill_missing_original_iats() const
-{
- return fill_missing_original_iats_;
-}
-
-//Returns true if PE headers should be updated automatically after rebuilding of imports
-bool import_rebuilder_settings::auto_set_to_pe_headers() const
-{
- return set_to_pe_headers_;
-}
-
-//Returns true if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true
-bool import_rebuilder_settings::zero_directory_entry_iat() const
-{
- return zero_directory_entry_iat_;
-}
-
-//Returns true if the last section should be stripped automatically, if imports are inside it
-bool import_rebuilder_settings::auto_strip_last_section_enabled() const
-{
- return auto_strip_last_section_;
-}
-
-//Sets offset from section start where import directory data will be placed
-void import_rebuilder_settings::set_offset_from_section_start(uint32_t offset)
-{
- offset_from_section_start_ = offset;
-}
-
-//Sets if Original import address table (IAT) will be rebuilt
-void import_rebuilder_settings::build_original_iat(bool enable)
-{
- build_original_iat_ = enable;
-}
-
-//Sets if Original import address and import address tables will not be rebuilt,
-//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
-void import_rebuilder_settings::save_iat_and_original_iat_rvas(bool enable, bool enable_rewrite_iat_and_original_iat_contents)
-{
- save_iat_and_original_iat_rvas_ = enable;
- if(save_iat_and_original_iat_rvas_)
- rewrite_iat_and_original_iat_contents_ = enable_rewrite_iat_and_original_iat_contents;
- else
- rewrite_iat_and_original_iat_contents_ = false;
-}
-
-//Sets if original missing IATs will be rebuilt
-//(only if IATs are saved)
-void import_rebuilder_settings::fill_missing_original_iats(bool enable)
-{
- fill_missing_original_iats_ = enable;
-}
-
-//Sets if PE headers should be updated automatically after rebuilding of imports
-void import_rebuilder_settings::auto_set_to_pe_headers(bool enable)
-{
- set_to_pe_headers_ = enable;
-}
-
-//Sets if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true
-void import_rebuilder_settings::zero_directory_entry_iat(bool enable)
-{
- zero_directory_entry_iat_ = enable;
-}
-
-//Sets if the last section should be stripped automatically, if imports are inside it, default true
-void import_rebuilder_settings::enable_auto_strip_last_section(bool enable)
-{
- auto_strip_last_section_ = enable;
-}
-
-//Default constructor
-imported_function::imported_function()
- :hint_(0), ordinal_(0), iat_va_(0)
-{}
-
-//Returns name of function
-const std::string& imported_function::get_name() const
-{
- return name_;
-}
-
-//Returns true if imported function has name (and hint)
-bool imported_function::has_name() const
-{
- return !name_.empty();
-}
-
-//Returns hint
-uint16_t imported_function::get_hint() const
-{
- return hint_;
-}
-
-//Returns ordinal of function
-uint16_t imported_function::get_ordinal() const
-{
- return ordinal_;
-}
-
-//Returns IAT entry VA (usable if image has both IAT and original IAT and is bound)
-uint64_t imported_function::get_iat_va() const
-{
- return iat_va_;
-}
-
-//Sets name of function
-void imported_function::set_name(const std::string& name)
-{
- name_ = name;
-}
-
-//Sets hint
-void imported_function::set_hint(uint16_t hint)
-{
- hint_ = hint;
-}
-
-//Sets ordinal
-void imported_function::set_ordinal(uint16_t ordinal)
-{
- ordinal_ = ordinal;
-}
-
-//Sets IAT entry VA (usable if image has both IAT and original IAT and is bound)
-void imported_function::set_iat_va(uint64_t va)
-{
- iat_va_ = va;
-}
-
-//Default constructor
-import_library::import_library()
- :rva_to_iat_(0), rva_to_original_iat_(0), timestamp_(0)
-{}
-
-//Returns name of library
-const std::string& import_library::get_name() const
-{
- return name_;
-}
-
-//Returns RVA to Import Address Table (IAT)
-uint32_t import_library::get_rva_to_iat() const
-{
- return rva_to_iat_;
-}
-
-//Returns RVA to Original Import Address Table (Original IAT)
-uint32_t import_library::get_rva_to_original_iat() const
-{
- return rva_to_original_iat_;
-}
-
-//Returns timestamp
-uint32_t import_library::get_timestamp() const
-{
- return timestamp_;
-}
-
-//Sets name of library
-void import_library::set_name(const std::string& name)
-{
- name_ = name;
-}
-
-//Sets RVA to Import Address Table (IAT)
-void import_library::set_rva_to_iat(uint32_t rva_to_iat)
-{
- rva_to_iat_ = rva_to_iat;
-}
-
-//Sets RVA to Original Import Address Table (Original IAT)
-void import_library::set_rva_to_original_iat(uint32_t rva_to_original_iat)
-{
- rva_to_original_iat_ = rva_to_original_iat;
-}
-
-//Sets timestamp
-void import_library::set_timestamp(uint32_t timestamp)
-{
- timestamp_ = timestamp;
-}
-
-//Returns imported functions list
-const import_library::imported_list& import_library::get_imported_functions() const
-{
- return imports_;
-}
-
-//Adds imported function
-void import_library::add_import(const imported_function& func)
-{
- imports_.push_back(func);
-}
-
-//Clears imported functions list
-void import_library::clear_imports()
-{
- imports_.clear();
-}
-
-const imported_functions_list get_imported_functions(const pe_base& pe)
-{
- return (pe.get_pe_type() == pe_type_32 ?
- get_imported_functions_base<pe_types_class_32>(pe)
- : get_imported_functions_base<pe_types_class_64>(pe));
-}
-
-const image_directory rebuild_imports(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings)
-{
- return (pe.get_pe_type() == pe_type_32 ?
- rebuild_imports_base<pe_types_class_32>(pe, imports, import_section, import_settings)
- : rebuild_imports_base<pe_types_class_64>(pe, imports, import_section, import_settings));
-}
-
-//Returns imported functions list with related libraries info
-template<typename PEClassType>
-const imported_functions_list get_imported_functions_base(const pe_base& pe)
-{
- imported_functions_list ret;
-
- //If image has no imports, return empty array
- if(!pe.has_imports())
- return ret;
-
- unsigned long current_descriptor_pos = pe.get_directory_rva(image_directory_entry_import);
- //Get first IMAGE_IMPORT_DESCRIPTOR
- image_import_descriptor import_descriptor = pe.section_data_from_rva<image_import_descriptor>(current_descriptor_pos, section_data_virtual, true);
-
- //Iterate them until we reach zero-element
- //We don't need to check correctness of this, because exception will be thrown
- //inside of loop if we go outsize of section
- while(import_descriptor.Name)
- {
- //Get imported library information
- import_library lib;
-
- unsigned long max_name_length;
- //Get byte count that we have for library name
- if((max_name_length = pe.section_data_length_from_rva(import_descriptor.Name, import_descriptor.Name, section_data_virtual, true)) < 2)
- throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
-
- //Get DLL name pointer
- const char* dll_name = pe.section_data_from_rva(import_descriptor.Name, section_data_virtual, true);
-
- //Check for null-termination
- if(!pe_utils::is_null_terminated(dll_name, max_name_length))
- throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
-
- //Set library name
- lib.set_name(dll_name);
- //Set library timestamp
- lib.set_timestamp(import_descriptor.TimeDateStamp);
- //Set library RVA to IAT and original IAT
- lib.set_rva_to_iat(import_descriptor.FirstThunk);
- lib.set_rva_to_original_iat(import_descriptor.OriginalFirstThunk);
-
- //Get RVA to IAT (it must be filled by loader when loading PE)
- uint32_t current_thunk_rva = import_descriptor.FirstThunk;
- typename PEClassType::BaseSize import_address_table = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_thunk_rva, section_data_virtual, true);
-
- //Get RVA to original IAT (lookup table), which must handle imported functions names
- //Some linkers leave this pointer zero-filled
- //Such image is valid, but it is not possible to restore imported functions names
- //afted image was loaded, because IAT becomes the only one table
- //containing both function names and function RVAs after loading
- uint32_t current_original_thunk_rva = import_descriptor.OriginalFirstThunk;
- typename PEClassType::BaseSize import_lookup_table = current_original_thunk_rva == 0 ? import_address_table : pe.section_data_from_rva<typename PEClassType::BaseSize>(current_original_thunk_rva, section_data_virtual, true);
- if(current_original_thunk_rva == 0)
- current_original_thunk_rva = current_thunk_rva;
-
- //List all imported functions for current DLL
- if(import_lookup_table != 0 && import_address_table != 0)
- {
- while(true)
- {
- //Imported function description
- imported_function func;
-
- //Get VA from IAT
- typename PEClassType::BaseSize address = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_thunk_rva, section_data_virtual, true);
- //Move pointer
- current_thunk_rva += sizeof(typename PEClassType::BaseSize);
-
- //Jump to next DLL if we finished with this one
- if(!address)
- break;
-
- func.set_iat_va(address);
-
- //Get VA from original IAT
- typename PEClassType::BaseSize lookup = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_original_thunk_rva, section_data_virtual, true);
- //Move pointer
- current_original_thunk_rva += sizeof(typename PEClassType::BaseSize);
-
- //Check if function is imported by ordinal
- if((lookup & PEClassType::ImportSnapFlag) != 0)
- {
- //Set function ordinal
- func.set_ordinal(static_cast<uint16_t>(lookup & 0xffff));
- }
- else
- {
- //Get byte count that we have for function name
- if(lookup > static_cast<uint32_t>(-1) - sizeof(uint16_t))
- throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
-
- //Get maximum available length of function name
- if((max_name_length = pe.section_data_length_from_rva(static_cast<uint32_t>(lookup + sizeof(uint16_t)), static_cast<uint32_t>(lookup + sizeof(uint16_t)), section_data_virtual, true)) < 2)
- throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
-
- //Get imported function name
- const char* func_name = pe.section_data_from_rva(static_cast<uint32_t>(lookup + sizeof(uint16_t)), section_data_virtual, true);
-
- //Check for null-termination
- if(!pe_utils::is_null_terminated(func_name, max_name_length))
- throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
-
- //HINT in import table is ORDINAL in export table
- uint16_t hint = pe.section_data_from_rva<uint16_t>(static_cast<uint32_t>(lookup), section_data_virtual, true);
-
- //Save hint and name
- func.set_name(func_name);
- func.set_hint(hint);
- }
-
- //Add function to list
- lib.add_import(func);
- }
- }
-
- //Check possible overflow
- if(!pe_utils::is_sum_safe(current_descriptor_pos, sizeof(image_import_descriptor)))
- throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
-
- //Go to next library
- current_descriptor_pos += sizeof(image_import_descriptor);
- import_descriptor = pe.section_data_from_rva<image_import_descriptor>(current_descriptor_pos, section_data_virtual, true);
-
- //Save import information
- ret.push_back(lib);
- }
-
- //Return resulting list
- return ret;
-}
-
-
-//Simple import directory rebuilder
-//You can get all image imports with get_imported_functions() function
-//You can use returned value to, for example, add new imported library with some functions
-//to the end of list of imported libraries
-//To keep PE file working, rebuild its imports with save_iat_and_original_iat_rvas = true (default)
-//Don't add new imported functions to existing imported library entries, because this can cause
-//rewriting of some used memory (or other IAT/orig.IAT fields) by system loader
-//The safest way is just adding import libraries with functions to the end of imported_functions_list array
-template<typename PEClassType>
-const image_directory rebuild_imports_base(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings)
-{
- //Check that import_section is attached to this PE image
- if(!pe.section_attached(import_section))
- throw pe_exception("Import section must be attached to PE file", pe_exception::section_is_not_attached);
-
- uint32_t needed_size = 0; //Calculate needed size for import structures and strings
- uint32_t needed_size_for_strings = 0; //Calculate needed size for import strings (library and function names and hints)
- uint32_t size_of_iat = 0; //Size of IAT structures
-
- needed_size += static_cast<uint32_t>((1 /* ending null descriptor */ + imports.size()) * sizeof(image_import_descriptor));
-
- //Enumerate imported functions
- for(imported_functions_list::const_iterator it = imports.begin(); it != imports.end(); ++it)
- {
- needed_size_for_strings += static_cast<uint32_t>((*it).get_name().length() + 1 /* nullbyte */);
-
- const import_library::imported_list& funcs = (*it).get_imported_functions();
-
- //IMAGE_THUNK_DATA
- size_of_iat += static_cast<uint32_t>(sizeof(typename PEClassType::BaseSize) * (1 /*ending null */ + funcs.size()));
-
- //Enumerate all imported functions in library
- for(import_library::imported_list::const_iterator f = funcs.begin(); f != funcs.end(); ++f)
- {
- if((*f).has_name())
- needed_size_for_strings += static_cast<uint32_t>((*f).get_name().length() + 1 /* nullbyte */ + sizeof(uint16_t) /* hint */);
- }
- }
-
- if(import_settings.build_original_iat() || import_settings.fill_missing_original_iats())
- needed_size += size_of_iat * 2; //We'll have two similar-sized IATs if we're building original IAT
- else
- needed_size += size_of_iat;
-
- needed_size += sizeof(typename PEClassType::BaseSize); //Maximum align for IAT and original IAT
-
- //Total needed size for import structures and strings
- needed_size += needed_size_for_strings;
-
- //Check if import_section is last one. If it's not, check if there's enough place for import data
- if(&import_section != &*(pe.get_image_sections().end() - 1) &&
- (import_section.empty() || pe_utils::align_up(import_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + import_settings.get_offset_from_section_start()))
- throw pe_exception("Insufficient space for import directory", pe_exception::insufficient_space);
-
- std::string& raw_data = import_section.get_raw_data();
-
- //This will be done only if image_section is the last section of image or for section with unaligned raw length of data
- if(raw_data.length() < needed_size + import_settings.get_offset_from_section_start())
- raw_data.resize(needed_size + import_settings.get_offset_from_section_start()); //Expand section raw data
-
- uint32_t current_string_pointer = import_settings.get_offset_from_section_start();/* we will paste structures after strings */
-
- //Position for IAT
- uint32_t current_pos_for_iat = pe_utils::align_up(static_cast<uint32_t>(needed_size_for_strings + import_settings.get_offset_from_section_start() + (1 + imports.size()) * sizeof(image_import_descriptor)), sizeof(typename PEClassType::BaseSize));
- //Position for original IAT
- uint32_t current_pos_for_original_iat = current_pos_for_iat + size_of_iat;
- //Position for import descriptors
- uint32_t current_pos_for_descriptors = needed_size_for_strings + import_settings.get_offset_from_section_start();
-
- //Build imports
- for(imported_functions_list::const_iterator it = imports.begin(); it != imports.end(); ++it)
- {
- //Create import descriptor
- image_import_descriptor descr;
- memset(&descr, 0, sizeof(descr));
- descr.TimeDateStamp = (*it).get_timestamp(); //Restore timestamp
- descr.Name = pe.rva_from_section_offset(import_section, current_string_pointer); //Library name RVA
-
- //If we should save IAT for current import descriptor
- bool save_iats_for_this_descriptor = import_settings.save_iat_and_original_iat_rvas() && (*it).get_rva_to_iat() != 0;
- //If we should write original IAT
- bool write_original_iat = (!save_iats_for_this_descriptor && import_settings.build_original_iat()) || import_settings.fill_missing_original_iats();
-
- //If we should rewrite saved original IAT for current import descriptor (without changing its position)
- bool rewrite_saved_original_iat = save_iats_for_this_descriptor && import_settings.rewrite_iat_and_original_iat_contents() && import_settings.build_original_iat();
- //If we should rewrite saved IAT for current import descriptor (without changing its position)
- bool rewrite_saved_iat = save_iats_for_this_descriptor && import_settings.rewrite_iat_and_original_iat_contents() && (*it).get_rva_to_iat() != 0;
-
- //Helper values if we're rewriting existing IAT or orig.IAT
- uint32_t original_first_thunk = 0;
- uint32_t first_thunk = 0;
-
- if(save_iats_for_this_descriptor)
- {
- //If there's no original IAT and we're asked to rebuild missing original IATs
- if(!(*it).get_rva_to_original_iat() && import_settings.fill_missing_original_iats())
- descr.OriginalFirstThunk = import_settings.build_original_iat() ? pe.rva_from_section_offset(import_section, current_pos_for_original_iat) : 0;
- else
- descr.OriginalFirstThunk = import_settings.build_original_iat() ? (*it).get_rva_to_original_iat() : 0;
-
- descr.FirstThunk = (*it).get_rva_to_iat();
-
- original_first_thunk = descr.OriginalFirstThunk;
- first_thunk = descr.FirstThunk;
-
- if(rewrite_saved_original_iat)
- {
- if((*it).get_rva_to_original_iat())
- write_original_iat = true;
- else
- rewrite_saved_original_iat = false;
- }
-
- if(rewrite_saved_iat)
- save_iats_for_this_descriptor = false;
- }
- else
- {
- //We are creating new IAT and original IAT (if needed)
- descr.OriginalFirstThunk = import_settings.build_original_iat() ? pe.rva_from_section_offset(import_section, current_pos_for_original_iat) : 0;
- descr.FirstThunk = pe.rva_from_section_offset(import_section, current_pos_for_iat);
- }
-
- //Save import descriptor
- memcpy(&raw_data[current_pos_for_descriptors], &descr, sizeof(descr));
- current_pos_for_descriptors += sizeof(descr);
-
- //Save library name
- memcpy(&raw_data[current_string_pointer], (*it).get_name().c_str(), (*it).get_name().length() + 1 /* nullbyte */);
- current_string_pointer += static_cast<uint32_t>((*it).get_name().length() + 1 /* nullbyte */);
-
- //List all imported functions
- const import_library::imported_list& funcs = (*it).get_imported_functions();
- for(import_library::imported_list::const_iterator f = funcs.begin(); f != funcs.end(); ++f)
- {
- if((*f).has_name()) //If function is imported by name
- {
- //Get RVA of IMAGE_IMPORT_BY_NAME
- typename PEClassType::BaseSize rva_of_named_import = pe.rva_from_section_offset(import_section, current_string_pointer);
-
- if(!save_iats_for_this_descriptor)
- {
- if(write_original_iat)
- {
- //We're creating original IATs - so we can write to IAT saved VA (because IMAGE_IMPORT_BY_NAME will be read
- //by PE loader from original IAT)
- typename PEClassType::BaseSize iat_value = static_cast<typename PEClassType::BaseSize>((*f).get_iat_va());
-
- if(rewrite_saved_iat)
- {
- if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(iat_value))
- throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(first_thunk, true), &iat_value, sizeof(iat_value));
-
- first_thunk += sizeof(iat_value);
- }
- else
- {
- memcpy(&raw_data[current_pos_for_iat], &iat_value, sizeof(iat_value));
- current_pos_for_iat += sizeof(rva_of_named_import);
- }
- }
- else
- {
- //Else - write to IAT RVA of IMAGE_IMPORT_BY_NAME
- if(rewrite_saved_iat)
- {
- if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(rva_of_named_import))
- throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(first_thunk, true), &rva_of_named_import, sizeof(rva_of_named_import));
-
- first_thunk += sizeof(rva_of_named_import);
- }
- else
- {
- memcpy(&raw_data[current_pos_for_iat], &rva_of_named_import, sizeof(rva_of_named_import));
- current_pos_for_iat += sizeof(rva_of_named_import);
- }
- }
- }
-
- if(write_original_iat)
- {
- if(rewrite_saved_original_iat)
- {
- if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(rva_of_named_import))
- throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(original_first_thunk, true), &rva_of_named_import, sizeof(rva_of_named_import));
-
- original_first_thunk += sizeof(rva_of_named_import);
- }
- else
- {
- //We're creating original IATs
- memcpy(&raw_data[current_pos_for_original_iat], &rva_of_named_import, sizeof(rva_of_named_import));
- current_pos_for_original_iat += sizeof(rva_of_named_import);
- }
- }
-
- //Write IMAGE_IMPORT_BY_NAME (WORD hint + string function name)
- uint16_t hint = (*f).get_hint();
- memcpy(&raw_data[current_string_pointer], &hint, sizeof(hint));
- memcpy(&raw_data[current_string_pointer + sizeof(uint16_t)], (*f).get_name().c_str(), (*f).get_name().length() + 1 /* nullbyte */);
- current_string_pointer += static_cast<uint32_t>((*f).get_name().length() + 1 /* nullbyte */ + sizeof(uint16_t) /* hint */);
- }
- else //Function is imported by ordinal
- {
- uint16_t ordinal = (*f).get_ordinal();
- typename PEClassType::BaseSize thunk_value = ordinal;
- thunk_value |= PEClassType::ImportSnapFlag; //Imported by ordinal
-
- if(!save_iats_for_this_descriptor)
- {
- if(write_original_iat)
- {
- //We're creating original IATs - so we can wtire to IAT saved VA (because ordinal will be read
- //by PE loader from original IAT)
- typename PEClassType::BaseSize iat_value = static_cast<typename PEClassType::BaseSize>((*f).get_iat_va());
- if(rewrite_saved_iat)
- {
- if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(iat_value))
- throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(first_thunk, true), &iat_value, sizeof(iat_value));
-
- first_thunk += sizeof(iat_value);
- }
- else
- {
- memcpy(&raw_data[current_pos_for_iat], &iat_value, sizeof(iat_value));
- current_pos_for_iat += sizeof(thunk_value);
- }
- }
- else
- {
- //Else - write ordinal to IAT
- if(rewrite_saved_iat)
- {
- if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(thunk_value))
- throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(first_thunk, true), &thunk_value, sizeof(thunk_value));
-
- first_thunk += sizeof(thunk_value);
- }
- else
- {
- memcpy(&raw_data[current_pos_for_iat], &thunk_value, sizeof(thunk_value));
- }
- }
- }
-
- //We're writing ordinal to original IAT slot
- if(write_original_iat)
- {
- if(rewrite_saved_original_iat)
- {
- if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(thunk_value))
- throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(original_first_thunk, true), &thunk_value, sizeof(thunk_value));
-
- original_first_thunk += sizeof(thunk_value);
- }
- else
- {
- memcpy(&raw_data[current_pos_for_original_iat], &thunk_value, sizeof(thunk_value));
- current_pos_for_original_iat += sizeof(thunk_value);
- }
- }
- }
- }
-
- if(!save_iats_for_this_descriptor)
- {
- //Ending null thunks
- typename PEClassType::BaseSize thunk_value = 0;
-
- if(rewrite_saved_iat)
- {
- if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(thunk_value))
- throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(first_thunk, true), &thunk_value, sizeof(thunk_value));
-
- first_thunk += sizeof(thunk_value);
- }
- else
- {
- memcpy(&raw_data[current_pos_for_iat], &thunk_value, sizeof(thunk_value));
- current_pos_for_iat += sizeof(thunk_value);
- }
- }
-
- if(write_original_iat)
- {
- //Ending null thunks
- typename PEClassType::BaseSize thunk_value = 0;
-
- if(rewrite_saved_original_iat)
- {
- if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(thunk_value))
- throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space);
-
- memcpy(pe.section_data_from_rva(original_first_thunk, true), &thunk_value, sizeof(thunk_value));
-
- original_first_thunk += sizeof(thunk_value);
- }
- else
- {
- memcpy(&raw_data[current_pos_for_original_iat], &thunk_value, sizeof(thunk_value));
- current_pos_for_original_iat += sizeof(thunk_value);
- }
- }
- }
-
- {
- //Null ending descriptor
- image_import_descriptor descr;
- memset(&descr, 0, sizeof(descr));
- memcpy(&raw_data[current_pos_for_descriptors], &descr, sizeof(descr));
- }
-
- //Strip data a little, if we saved some place
- //We're allocating more space than needed, if present original IAT and IAT are saved
- raw_data.resize(current_pos_for_original_iat);
-
- //Adjust section raw and virtual sizes
- pe.recalculate_section_sizes(import_section, import_settings.auto_strip_last_section_enabled());
-
- //Return information about rebuilt import directory
- image_directory ret(pe.rva_from_section_offset(import_section, import_settings.get_offset_from_section_start() + needed_size_for_strings), needed_size - needed_size_for_strings);
-
- //If auto-rewrite of PE headers is required
- if(import_settings.auto_set_to_pe_headers())
- {
- pe.set_directory_rva(image_directory_entry_import, ret.get_rva());
- pe.set_directory_size(image_directory_entry_import, ret.get_size());
-
- //If we are requested to zero IMAGE_DIRECTORY_ENTRY_IAT also
- if(import_settings.zero_directory_entry_iat())
- {
- pe.set_directory_rva(image_directory_entry_iat, 0);
- pe.set_directory_size(image_directory_entry_iat, 0);
- }
- }
-
- return ret;
-}
-}
diff --git a/tools/pe_bliss/pe_imports.h b/tools/pe_bliss/pe_imports.h
deleted file mode 100644
index 681b5b59bd..0000000000
--- a/tools/pe_bliss/pe_imports.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include <string>
-#include "pe_structures.h"
-#include "pe_directory.h"
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-//Class representing imported function
-class imported_function
-{
-public:
- //Default constructor
- imported_function();
-
- //Returns true if imported function has name (and hint)
- bool has_name() const;
- //Returns name of function
- const std::string& get_name() const;
- //Returns hint
- uint16_t get_hint() const;
- //Returns ordinal of function
- uint16_t get_ordinal() const;
-
- //Returns IAT entry VA (usable if image has both IAT and original IAT and is bound)
- uint64_t get_iat_va() const;
-
-public: //Setters do not change everything inside image, they are used by PE class
- //You also can use them to rebuild image imports
- //Sets name of function
- void set_name(const std::string& name);
- //Sets hint
- void set_hint(uint16_t hint);
- //Sets ordinal
- void set_ordinal(uint16_t ordinal);
-
- //Sets IAT entry VA (usable if image has both IAT and original IAT and is bound)
- void set_iat_va(uint64_t rva);
-
-private:
- std::string name_; //Function name
- uint16_t hint_; //Hint
- uint16_t ordinal_; //Ordinal
- uint64_t iat_va_;
-};
-
-//Class representing imported library information
-class import_library
-{
-public:
- typedef std::vector<imported_function> imported_list;
-
-public:
- //Default constructor
- import_library();
-
- //Returns name of library
- const std::string& get_name() const;
- //Returns RVA to Import Address Table (IAT)
- uint32_t get_rva_to_iat() const;
- //Returns RVA to Original Import Address Table (Original IAT)
- uint32_t get_rva_to_original_iat() const;
- //Returns timestamp
- uint32_t get_timestamp() const;
-
- //Returns imported functions list
- const imported_list& get_imported_functions() const;
-
-public: //Setters do not change everything inside image, they are used by PE class
- //You also can use them to rebuild image imports
- //Sets name of library
- void set_name(const std::string& name);
- //Sets RVA to Import Address Table (IAT)
- void set_rva_to_iat(uint32_t rva_to_iat);
- //Sets RVA to Original Import Address Table (Original IAT)
- void set_rva_to_original_iat(uint32_t rva_to_original_iat);
- //Sets timestamp
- void set_timestamp(uint32_t timestamp);
-
- //Adds imported function
- void add_import(const imported_function& func);
- //Clears imported functions list
- void clear_imports();
-
-private:
- std::string name_; //Library name
- uint32_t rva_to_iat_; //RVA to IAT
- uint32_t rva_to_original_iat_; //RVA to original IAT
- uint32_t timestamp_; //DLL TimeStamp
-
- imported_list imports_;
-};
-
-//Simple import directory rebuilder
-//Class representing import rebuilder advanced settings
-class import_rebuilder_settings
-{
-public:
- //Default constructor
- //Default constructor
- //If set_to_pe_headers = true, IMAGE_DIRECTORY_ENTRY_IMPORT entry will be reset
- //to new value after import rebuilding
- //If auto_zero_directory_entry_iat = true, IMAGE_DIRECTORY_ENTRY_IAT will be set to zero
- //IMAGE_DIRECTORY_ENTRY_IAT is used by loader to temporarily make section, where IMAGE_DIRECTORY_ENTRY_IAT RVA points, writeable
- //to be able to modify IAT thunks
- explicit import_rebuilder_settings(bool set_to_pe_headers = true, bool auto_zero_directory_entry_iat = false);
-
- //Returns offset from section start where import directory data will be placed
- uint32_t get_offset_from_section_start() const;
- //Returns true if Original import address table (IAT) will be rebuilt
- bool build_original_iat() const;
-
- //Returns true if Original import address and import address tables will not be rebuilt,
- //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
- bool save_iat_and_original_iat_rvas() const;
- //Returns true if Original import address and import address tables contents will be rewritten
- //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
- //and save_iat_and_original_iat_rvas is true
- bool rewrite_iat_and_original_iat_contents() const;
-
- //Returns true if original missing IATs will be rebuilt
- //(only if IATs are saved)
- bool fill_missing_original_iats() const;
- //Returns true if PE headers should be updated automatically after rebuilding of imports
- bool auto_set_to_pe_headers() const;
- //Returns true if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true
- bool zero_directory_entry_iat() const;
-
- //Returns true if the last section should be stripped automatically, if imports are inside it
- bool auto_strip_last_section_enabled() const;
-
-public: //Setters
- //Sets offset from section start where import directory data will be placed
- void set_offset_from_section_start(uint32_t offset);
- //Sets if Original import address table (IAT) will be rebuilt
- void build_original_iat(bool enable);
- //Sets if Original import address and import address tables will not be rebuilt,
- //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
- //enable_rewrite_iat_and_original_iat_contents sets if Original import address and import address tables contents will be rewritten
- //works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
- //and save_iat_and_original_iat_rvas is true
- void save_iat_and_original_iat_rvas(bool enable, bool enable_rewrite_iat_and_original_iat_contents = false);
- //Sets if original missing IATs will be rebuilt
- //(only if IATs are saved)
- void fill_missing_original_iats(bool enable);
- //Sets if PE headers should be updated automatically after rebuilding of imports
- void auto_set_to_pe_headers(bool enable);
- //Sets if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true
- void zero_directory_entry_iat(bool enable);
-
- //Sets if the last section should be stripped automatically, if imports are inside it, default true
- void enable_auto_strip_last_section(bool enable);
-
-private:
- uint32_t offset_from_section_start_;
- bool build_original_iat_;
- bool save_iat_and_original_iat_rvas_;
- bool fill_missing_original_iats_;
- bool set_to_pe_headers_;
- bool zero_directory_entry_iat_;
- bool rewrite_iat_and_original_iat_contents_;
- bool auto_strip_last_section_;
-};
-
-typedef std::vector<import_library> imported_functions_list;
-
-
-//Returns imported functions list with related libraries info
-const imported_functions_list get_imported_functions(const pe_base& pe);
-
-template<typename PEClassType>
-const imported_functions_list get_imported_functions_base(const pe_base& pe);
-
-
-//You can get all image imports with get_imported_functions() function
-//You can use returned value to, for example, add new imported library with some functions
-//to the end of list of imported libraries
-//To keep PE file working, rebuild its imports with save_iat_and_original_iat_rvas = true (default)
-//Don't add new imported functions to existing imported library entries, because this can cause
-//rewriting of some used memory (or other IAT/orig.IAT fields) by system loader
-//The safest way is just adding import libraries with functions to the end of imported_functions_list array
-const image_directory rebuild_imports(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings = import_rebuilder_settings());
-
-template<typename PEClassType>
-const image_directory rebuild_imports_base(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings = import_rebuilder_settings());
-}
diff --git a/tools/pe_bliss/pe_load_config.cpp b/tools/pe_bliss/pe_load_config.cpp
deleted file mode 100644
index c05895fecd..0000000000
--- a/tools/pe_bliss/pe_load_config.cpp
+++ /dev/null
@@ -1,557 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <algorithm>
-#include <string.h>
-#include "pe_load_config.h"
-#include "pe_properties_generic.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//IMAGE CONFIG
-//Default constructor
-image_config_info::image_config_info()
- :time_stamp_(0),
- major_version_(0), minor_version_(0),
- global_flags_clear_(0), global_flags_set_(0),
- critical_section_default_timeout_(0),
- decommit_free_block_threshold_(0), decommit_total_free_threshold_(0),
- lock_prefix_table_va_(0),
- max_allocation_size_(0),
- virtual_memory_threshold_(0),
- process_affinity_mask_(0),
- process_heap_flags_(0),
- service_pack_version_(0),
- edit_list_va_(0),
- security_cookie_va_(0),
- se_handler_table_va_(0),
- se_handler_count_(0)
-{}
-
-//Constructors from PE structures
-template<typename ConfigStructure>
-image_config_info::image_config_info(const ConfigStructure& info)
- :time_stamp_(info.TimeDateStamp),
- major_version_(info.MajorVersion), minor_version_(info.MinorVersion),
- global_flags_clear_(info.GlobalFlagsClear), global_flags_set_(info.GlobalFlagsSet),
- critical_section_default_timeout_(info.CriticalSectionDefaultTimeout),
- decommit_free_block_threshold_(info.DeCommitFreeBlockThreshold), decommit_total_free_threshold_(info.DeCommitTotalFreeThreshold),
- lock_prefix_table_va_(info.LockPrefixTable),
- max_allocation_size_(info.MaximumAllocationSize),
- virtual_memory_threshold_(info.VirtualMemoryThreshold),
- process_affinity_mask_(info.ProcessAffinityMask),
- process_heap_flags_(info.ProcessHeapFlags),
- service_pack_version_(info.CSDVersion),
- edit_list_va_(info.EditList),
- security_cookie_va_(info.SecurityCookie),
- se_handler_table_va_(info.SEHandlerTable),
- se_handler_count_(info.SEHandlerCount)
-{}
-
-//Instantiate template constructor with needed structures
-template image_config_info::image_config_info(const image_load_config_directory32& info);
-template image_config_info::image_config_info(const image_load_config_directory64& info);
-
-//Returns the date and time stamp value
-uint32_t image_config_info::get_time_stamp() const
-{
- return time_stamp_;
-}
-
-//Returns major version number
-uint16_t image_config_info::get_major_version() const
-{
- return major_version_;
-}
-
-//Returns minor version number
-uint16_t image_config_info::get_minor_version() const
-{
- return minor_version_;
-}
-
-//Returns clear global flags
-uint32_t image_config_info::get_global_flags_clear() const
-{
- return global_flags_clear_;
-}
-
-//Returns set global flags
-uint32_t image_config_info::get_global_flags_set() const
-{
- return global_flags_set_;
-}
-
-//Returns critical section default timeout
-uint32_t image_config_info::get_critical_section_default_timeout() const
-{
- return critical_section_default_timeout_;
-}
-
-//Get the size of the minimum block that
-//must be freed before it is freed (de-committed), in bytes
-uint64_t image_config_info::get_decommit_free_block_threshold() const
-{
- return decommit_free_block_threshold_;
-}
-
-//Returns the size of the minimum total memory
-//that must be freed in the process heap before it is freed (de-committed), in bytes
-uint64_t image_config_info::get_decommit_total_free_threshold() const
-{
- return decommit_total_free_threshold_;
-}
-
-//Returns VA of a list of addresses where the LOCK prefix is used
-uint64_t image_config_info::get_lock_prefix_table_va() const
-{
- return lock_prefix_table_va_;
-}
-
-//Returns the maximum allocation size, in bytes
-uint64_t image_config_info::get_max_allocation_size() const
-{
- return max_allocation_size_;
-}
-
-//Returns the maximum block size that can be allocated from heap segments, in bytes
-uint64_t image_config_info::get_virtual_memory_threshold() const
-{
- return virtual_memory_threshold_;
-}
-
-//Returns process affinity mask
-uint64_t image_config_info::get_process_affinity_mask() const
-{
- return process_affinity_mask_;
-}
-
-//Returns process heap flags
-uint32_t image_config_info::get_process_heap_flags() const
-{
- return process_heap_flags_;
-}
-
-//Returns service pack version (CSDVersion)
-uint16_t image_config_info::get_service_pack_version() const
-{
- return service_pack_version_;
-}
-
-//Returns VA of edit list (reserved by system)
-uint64_t image_config_info::get_edit_list_va() const
-{
- return edit_list_va_;
-}
-
-//Returns a pointer to a cookie that is used by Visual C++ or GS implementation
-uint64_t image_config_info::get_security_cookie_va() const
-{
- return security_cookie_va_;
-}
-
-//Returns VA of the sorted table of RVAs of each valid, unique handler in the image
-uint64_t image_config_info::get_se_handler_table_va() const
-{
- return se_handler_table_va_;
-}
-
-//Returns the count of unique handlers in the table
-uint64_t image_config_info::get_se_handler_count() const
-{
- return se_handler_count_;
-}
-
-//Returns SE Handler RVA list
-const image_config_info::se_handler_list& image_config_info::get_se_handler_rvas() const
-{
- return se_handlers_;
-}
-
-//Returns Lock Prefix RVA list
-const image_config_info::lock_prefix_rva_list& image_config_info::get_lock_prefix_rvas() const
-{
- return lock_prefixes_;
-}
-
-//Adds SE Handler RVA to list
-void image_config_info::add_se_handler_rva(uint32_t rva)
-{
- se_handlers_.push_back(rva);
-}
-
-//Clears SE Handler list
-void image_config_info::clear_se_handler_list()
-{
- se_handlers_.clear();
-}
-
-//Adds Lock Prefix RVA to list
-void image_config_info::add_lock_prefix_rva(uint32_t rva)
-{
- lock_prefixes_.push_back(rva);
-}
-
-//Clears Lock Prefix list
-void image_config_info::clear_lock_prefix_list()
-{
- lock_prefixes_.clear();
-}
-
-//Sets the date and time stamp value
-void image_config_info::set_time_stamp(uint32_t time_stamp)
-{
- time_stamp_ = time_stamp;
-}
-
-//Sets major version number
-void image_config_info::set_major_version(uint16_t major_version)
-{
- major_version_ = major_version;
-}
-
-//Sets minor version number
-void image_config_info::set_minor_version(uint16_t minor_version)
-{
- minor_version_ = minor_version;
-}
-
-//Sets clear global flags
-void image_config_info::set_global_flags_clear(uint32_t global_flags_clear)
-{
- global_flags_clear_ = global_flags_clear;
-}
-
-//Sets set global flags
-void image_config_info::set_global_flags_set(uint32_t global_flags_set)
-{
- global_flags_set_ = global_flags_set;
-}
-
-//Sets critical section default timeout
-void image_config_info::set_critical_section_default_timeout(uint32_t critical_section_default_timeout)
-{
- critical_section_default_timeout_ = critical_section_default_timeout;
-}
-
-//Sets the size of the minimum block that
-//must be freed before it is freed (de-committed), in bytes
-void image_config_info::set_decommit_free_block_threshold(uint64_t decommit_free_block_threshold)
-{
- decommit_free_block_threshold_ = decommit_free_block_threshold;
-}
-
-//Sets the size of the minimum total memory
-//that must be freed in the process heap before it is freed (de-committed), in bytes
-void image_config_info::set_decommit_total_free_threshold(uint64_t decommit_total_free_threshold)
-{
- decommit_total_free_threshold_ = decommit_total_free_threshold;
-}
-
-//Sets VA of a list of addresses where the LOCK prefix is used
-//If you rebuild this list, VA will be re-assigned automatically
-void image_config_info::set_lock_prefix_table_va(uint64_t lock_prefix_table_va)
-{
- lock_prefix_table_va_ = lock_prefix_table_va;
-}
-
-//Sets the maximum allocation size, in bytes
-void image_config_info::set_max_allocation_size(uint64_t max_allocation_size)
-{
- max_allocation_size_ = max_allocation_size;
-}
-
-//Sets the maximum block size that can be allocated from heap segments, in bytes
-void image_config_info::set_virtual_memory_threshold(uint64_t virtual_memory_threshold)
-{
- virtual_memory_threshold_ = virtual_memory_threshold;
-}
-
-//Sets process affinity mask
-void image_config_info::set_process_affinity_mask(uint64_t process_affinity_mask)
-{
- process_affinity_mask_ = process_affinity_mask;
-}
-
-//Sets process heap flags
-void image_config_info::set_process_heap_flags(uint32_t process_heap_flags)
-{
- process_heap_flags_ = process_heap_flags;
-}
-
-//Sets service pack version (CSDVersion)
-void image_config_info::set_service_pack_version(uint16_t service_pack_version)
-{
- service_pack_version_ = service_pack_version;
-}
-
-//Sets VA of edit list (reserved by system)
-void image_config_info::set_edit_list_va(uint64_t edit_list_va)
-{
- edit_list_va_ = edit_list_va;
-}
-
-//Sets a pointer to a cookie that is used by Visual C++ or GS implementation
-void image_config_info::set_security_cookie_va(uint64_t security_cookie_va)
-{
- security_cookie_va_ = security_cookie_va;
-}
-
-//Sets VA of the sorted table of RVAs of each valid, unique handler in the image
-//If you rebuild this list, VA will be re-assigned automatically
-void image_config_info::set_se_handler_table_va(uint64_t se_handler_table_va)
-{
- se_handler_table_va_ = se_handler_table_va;
-}
-
-//Returns SE Handler RVA list
-image_config_info::se_handler_list& image_config_info::get_se_handler_rvas()
-{
- return se_handlers_;
-}
-
-//Returns Lock Prefix RVA list
-image_config_info::lock_prefix_rva_list& image_config_info::get_lock_prefix_rvas()
-{
- return lock_prefixes_;
-}
-
-//Returns image config info
-//If image does not have config info, throws an exception
-const image_config_info get_image_config(const pe_base& pe)
-{
- return pe.get_pe_type() == pe_type_32
- ? get_image_config_base<pe_types_class_32>(pe)
- : get_image_config_base<pe_types_class_64>(pe);
-}
-
-//Image config rebuilder
-const image_directory rebuild_image_config(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start, bool write_se_handlers, bool write_lock_prefixes, bool save_to_pe_header, bool auto_strip_last_section)
-{
- return pe.get_pe_type() == pe_type_32
- ? rebuild_image_config_base<pe_types_class_32>(pe, info, image_config_section, offset_from_section_start, write_se_handlers, write_lock_prefixes, save_to_pe_header, auto_strip_last_section)
- : rebuild_image_config_base<pe_types_class_64>(pe, info, image_config_section, offset_from_section_start, write_se_handlers, write_lock_prefixes, save_to_pe_header, auto_strip_last_section);
-}
-
-
-//Returns image config info
-//If image does not have config info, throws an exception
-template<typename PEClassType>
-const image_config_info get_image_config_base(const pe_base& pe)
-{
- //Check if image has config directory
- if(!pe.has_config())
- throw pe_exception("Image does not have load config directory", pe_exception::directory_does_not_exist);
-
- //Get load config structure
- typename PEClassType::ConfigStruct config_info = pe.section_data_from_rva<typename PEClassType::ConfigStruct>(pe.get_directory_rva(image_directory_entry_load_config), section_data_virtual);
-
- //Check size of config directory
- if(config_info.Size != sizeof(config_info))
- throw pe_exception("Incorrect (or old) load config directory", pe_exception::incorrect_config_directory);
-
- //Fill return structure
- image_config_info ret(config_info);
-
- //Check possible overflow
- if(config_info.SEHandlerCount >= pe_utils::max_dword / sizeof(uint32_t)
- || config_info.SEHandlerTable >= static_cast<typename PEClassType::BaseSize>(-1) - config_info.SEHandlerCount * sizeof(uint32_t))
- throw pe_exception("Incorrect load config directory", pe_exception::incorrect_config_directory);
-
- //Read sorted SE handler RVA list (if any)
- for(typename PEClassType::BaseSize i = 0; i != config_info.SEHandlerCount; ++i)
- ret.add_se_handler_rva(pe.section_data_from_va<uint32_t>(static_cast<typename PEClassType::BaseSize>(config_info.SEHandlerTable + i * sizeof(uint32_t))));
-
- if(config_info.LockPrefixTable)
- {
- //Read Lock Prefix VA list (if any)
- unsigned long current = 0;
- while(true)
- {
- typename PEClassType::BaseSize lock_prefix_va = pe.section_data_from_va<typename PEClassType::BaseSize>(static_cast<typename PEClassType::BaseSize>(config_info.LockPrefixTable + current * sizeof(typename PEClassType::BaseSize)));
- if(!lock_prefix_va)
- break;
-
- ret.add_lock_prefix_rva(pe.va_to_rva(lock_prefix_va));
-
- ++current;
- }
- }
-
- return ret;
-}
-
-//Image config directory rebuilder
-//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped
-//If write_se_handlers = true, SE Handlers list will be written just after image config directory structure
-//If write_lock_prefixes = true, Lock Prefixes address list will be written just after image config directory structure
-template<typename PEClassType>
-const image_directory rebuild_image_config_base(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start, bool write_se_handlers, bool write_lock_prefixes, bool save_to_pe_header, bool auto_strip_last_section)
-{
- //Check that image_config_section is attached to this PE image
- if(!pe.section_attached(image_config_section))
- throw pe_exception("Image Config section must be attached to PE file", pe_exception::section_is_not_attached);
-
- uint32_t alignment = pe_utils::align_up(offset_from_section_start, sizeof(typename PEClassType::BaseSize)) - offset_from_section_start;
-
- uint32_t needed_size = sizeof(typename PEClassType::ConfigStruct); //Calculate needed size for Image Config table
-
- uint32_t image_config_data_pos = offset_from_section_start + alignment;
-
- uint32_t current_pos_of_se_handlers = 0;
- uint32_t current_pos_of_lock_prefixes = 0;
-
- if(write_se_handlers)
- {
- current_pos_of_se_handlers = needed_size + image_config_data_pos;
- needed_size += static_cast<uint32_t>(info.get_se_handler_rvas().size()) * sizeof(uint32_t); //RVAs of SE Handlers
- }
-
- if(write_lock_prefixes)
- {
- current_pos_of_lock_prefixes = needed_size + image_config_data_pos;
- needed_size += static_cast<uint32_t>((info.get_lock_prefix_rvas().size() + 1) * sizeof(typename PEClassType::BaseSize)); //VAs of Lock Prefixes (and ending null element)
- }
-
- //Check if image_config_section is last one. If it's not, check if there's enough place for Image Config data
- if(&image_config_section != &*(pe.get_image_sections().end() - 1) &&
- (image_config_section.empty() || pe_utils::align_up(image_config_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + image_config_data_pos))
- throw pe_exception("Insufficient space for TLS directory", pe_exception::insufficient_space);
-
- std::string& raw_data = image_config_section.get_raw_data();
-
- //This will be done only if image_config_section is the last section of image or for section with unaligned raw length of data
- if(raw_data.length() < needed_size + image_config_data_pos)
- raw_data.resize(needed_size + image_config_data_pos); //Expand section raw data
-
- //Create and fill Image Config structure
- typename PEClassType::ConfigStruct image_config_section_struct = {0};
- image_config_section_struct.Size = sizeof(image_config_section_struct);
- image_config_section_struct.TimeDateStamp = info.get_time_stamp();
- image_config_section_struct.MajorVersion = info.get_major_version();
- image_config_section_struct.MinorVersion = info.get_minor_version();
- image_config_section_struct.GlobalFlagsClear = info.get_global_flags_clear();
- image_config_section_struct.GlobalFlagsSet = info.get_global_flags_set();
- image_config_section_struct.CriticalSectionDefaultTimeout = info.get_critical_section_default_timeout();
- image_config_section_struct.DeCommitFreeBlockThreshold = static_cast<typename PEClassType::BaseSize>(info.get_decommit_free_block_threshold());
- image_config_section_struct.DeCommitTotalFreeThreshold = static_cast<typename PEClassType::BaseSize>(info.get_decommit_total_free_threshold());
- image_config_section_struct.MaximumAllocationSize = static_cast<typename PEClassType::BaseSize>(info.get_max_allocation_size());
- image_config_section_struct.VirtualMemoryThreshold = static_cast<typename PEClassType::BaseSize>(info.get_virtual_memory_threshold());
- image_config_section_struct.ProcessHeapFlags = info.get_process_heap_flags();
- image_config_section_struct.ProcessAffinityMask = static_cast<typename PEClassType::BaseSize>(info.get_process_affinity_mask());
- image_config_section_struct.CSDVersion = info.get_service_pack_version();
- image_config_section_struct.EditList = static_cast<typename PEClassType::BaseSize>(info.get_edit_list_va());
- image_config_section_struct.SecurityCookie = static_cast<typename PEClassType::BaseSize>(info.get_security_cookie_va());
- image_config_section_struct.SEHandlerCount = static_cast<typename PEClassType::BaseSize>(info.get_se_handler_rvas().size());
-
-
- if(write_se_handlers)
- {
- if(info.get_se_handler_rvas().empty())
- {
- write_se_handlers = false;
- image_config_section_struct.SEHandlerTable = 0;
- }
- else
- {
- typename PEClassType::BaseSize va;
- pe.rva_to_va(pe.rva_from_section_offset(image_config_section, current_pos_of_se_handlers), va);
- image_config_section_struct.SEHandlerTable = va;
- }
- }
- else
- {
- image_config_section_struct.SEHandlerTable = static_cast<typename PEClassType::BaseSize>(info.get_se_handler_table_va());
- }
-
- if(write_lock_prefixes)
- {
- if(info.get_lock_prefix_rvas().empty())
- {
- write_lock_prefixes = false;
- image_config_section_struct.LockPrefixTable = 0;
- }
- else
- {
- typename PEClassType::BaseSize va;
- pe.rva_to_va(pe.rva_from_section_offset(image_config_section, current_pos_of_lock_prefixes), va);
- image_config_section_struct.LockPrefixTable = va;
- }
- }
- else
- {
- image_config_section_struct.LockPrefixTable = static_cast<typename PEClassType::BaseSize>(info.get_lock_prefix_table_va());
- }
-
- //Write image config section
- memcpy(&raw_data[image_config_data_pos], &image_config_section_struct, sizeof(image_config_section_struct));
-
- if(write_se_handlers)
- {
- //Sort SE Handlers list
- image_config_info::se_handler_list sorted_list = info.get_se_handler_rvas();
- std::sort(sorted_list.begin(), sorted_list.end());
-
- //Write SE Handlers table
- for(image_config_info::se_handler_list::const_iterator it = sorted_list.begin(); it != sorted_list.end(); ++it)
- {
- uint32_t se_handler_rva = *it;
- memcpy(&raw_data[current_pos_of_se_handlers], &se_handler_rva, sizeof(se_handler_rva));
- current_pos_of_se_handlers += sizeof(se_handler_rva);
- }
- }
-
- if(write_lock_prefixes)
- {
- //Write Lock Prefixes VA list
- for(image_config_info::lock_prefix_rva_list::const_iterator it = info.get_lock_prefix_rvas().begin(); it != info.get_lock_prefix_rvas().end(); ++it)
- {
- typename PEClassType::BaseSize lock_prefix_va;
- pe.rva_to_va(*it, lock_prefix_va);
- memcpy(&raw_data[current_pos_of_lock_prefixes], &lock_prefix_va, sizeof(lock_prefix_va));
- current_pos_of_lock_prefixes += sizeof(lock_prefix_va);
- }
-
- {
- //Ending null VA
- typename PEClassType::BaseSize lock_prefix_va = 0;
- memcpy(&raw_data[current_pos_of_lock_prefixes], &lock_prefix_va, sizeof(lock_prefix_va));
- }
- }
-
- //Adjust section raw and virtual sizes
- pe.recalculate_section_sizes(image_config_section, auto_strip_last_section);
-
- image_directory ret(pe.rva_from_section_offset(image_config_section, image_config_data_pos), sizeof(typename PEClassType::ConfigStruct));
-
- //If auto-rewrite of PE headers is required
- if(save_to_pe_header)
- {
- pe.set_directory_rva(image_directory_entry_load_config, ret.get_rva());
- pe.set_directory_size(image_directory_entry_load_config, ret.get_size());
- }
-
- return ret;
-}
-
-}
diff --git a/tools/pe_bliss/pe_load_config.h b/tools/pe_bliss/pe_load_config.h
deleted file mode 100644
index cb24072de7..0000000000
--- a/tools/pe_bliss/pe_load_config.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include "pe_structures.h"
-#include "pe_base.h"
-#include "pe_directory.h"
-
-namespace pe_bliss
-{
-//Class representing image configuration information
-class image_config_info
-{
-public:
- typedef std::vector<uint32_t> se_handler_list;
- typedef std::vector<uint32_t> lock_prefix_rva_list;
-
-public:
- //Default constructor
- image_config_info();
- //Constructors from PE structures (no checks)
- template<typename ConfigStructure>
- explicit image_config_info(const ConfigStructure& info);
-
- //Returns the date and time stamp value
- uint32_t get_time_stamp() const;
- //Returns major version number
- uint16_t get_major_version() const;
- //Returns minor version number
- uint16_t get_minor_version() const;
- //Returns clear global flags
- uint32_t get_global_flags_clear() const;
- //Returns set global flags
- uint32_t get_global_flags_set() const;
- //Returns critical section default timeout
- uint32_t get_critical_section_default_timeout() const;
- //Get the size of the minimum block that
- //must be freed before it is freed (de-committed), in bytes
- uint64_t get_decommit_free_block_threshold() const;
- //Returns the size of the minimum total memory
- //that must be freed in the process heap before it is freed (de-committed), in bytes
- uint64_t get_decommit_total_free_threshold() const;
- //Returns VA of a list of addresses where the LOCK prefix is used
- uint64_t get_lock_prefix_table_va() const;
- //Returns the maximum allocation size, in bytes
- uint64_t get_max_allocation_size() const;
- //Returns the maximum block size that can be allocated from heap segments, in bytes
- uint64_t get_virtual_memory_threshold() const;
- //Returns process affinity mask
- uint64_t get_process_affinity_mask() const;
- //Returns process heap flags
- uint32_t get_process_heap_flags() const;
- //Returns service pack version (CSDVersion)
- uint16_t get_service_pack_version() const;
- //Returns VA of edit list (reserved by system)
- uint64_t get_edit_list_va() const;
- //Returns a pointer to a cookie that is used by Visual C++ or GS implementation
- uint64_t get_security_cookie_va() const;
- //Returns VA of the sorted table of RVAs of each valid, unique handler in the image
- uint64_t get_se_handler_table_va() const;
- //Returns the count of unique handlers in the table
- uint64_t get_se_handler_count() const;
-
- //Returns SE Handler RVA list
- const se_handler_list& get_se_handler_rvas() const;
-
- //Returns Lock Prefix RVA list
- const lock_prefix_rva_list& get_lock_prefix_rvas() const;
-
-public: //These functions do not change everything inside image, they are used by PE class
- //Also you can use these functions to rebuild image config directory
-
- //Adds SE Handler RVA to list
- void add_se_handler_rva(uint32_t rva);
- //Clears SE Handler list
- void clear_se_handler_list();
-
- //Adds Lock Prefix RVA to list
- void add_lock_prefix_rva(uint32_t rva);
- //Clears Lock Prefix list
- void clear_lock_prefix_list();
-
- //Sets the date and time stamp value
- void set_time_stamp(uint32_t time_stamp);
- //Sets major version number
- void set_major_version(uint16_t major_version);
- //Sets minor version number
- void set_minor_version(uint16_t minor_version);
- //Sets clear global flags
- void set_global_flags_clear(uint32_t global_flags_clear);
- //Sets set global flags
- void set_global_flags_set(uint32_t global_flags_set);
- //Sets critical section default timeout
- void set_critical_section_default_timeout(uint32_t critical_section_default_timeout);
- //Sets the size of the minimum block that
- //must be freed before it is freed (de-committed), in bytes
- void set_decommit_free_block_threshold(uint64_t decommit_free_block_threshold);
- //Sets the size of the minimum total memory
- //that must be freed in the process heap before it is freed (de-committed), in bytes
- void set_decommit_total_free_threshold(uint64_t decommit_total_free_threshold);
- //Sets VA of a list of addresses where the LOCK prefix is used
- //If you rebuild this list, VA will be re-assigned automatically
- void set_lock_prefix_table_va(uint64_t lock_prefix_table_va);
- //Sets the maximum allocation size, in bytes
- void set_max_allocation_size(uint64_t max_allocation_size);
- //Sets the maximum block size that can be allocated from heap segments, in bytes
- void set_virtual_memory_threshold(uint64_t virtual_memory_threshold);
- //Sets process affinity mask
- void set_process_affinity_mask(uint64_t process_affinity_mask);
- //Sets process heap flags
- void set_process_heap_flags(uint32_t process_heap_flags);
- //Sets service pack version (CSDVersion)
- void set_service_pack_version(uint16_t service_pack_version);
- //Sets VA of edit list (reserved by system)
- void set_edit_list_va(uint64_t edit_list_va);
- //Sets a pointer to a cookie that is used by Visual C++ or GS implementation
- void set_security_cookie_va(uint64_t security_cookie_va);
- //Sets VA of the sorted table of RVAs of each valid, unique handler in the image
- //If you rebuild this list, VA will be re-assigned automatically
- void set_se_handler_table_va(uint64_t se_handler_table_va);
-
- //Returns SE Handler RVA list
- se_handler_list& get_se_handler_rvas();
-
- //Returns Lock Prefix RVA list
- lock_prefix_rva_list& get_lock_prefix_rvas();
-
-private:
- uint32_t time_stamp_;
- uint16_t major_version_, minor_version_;
- uint32_t global_flags_clear_, global_flags_set_;
- uint32_t critical_section_default_timeout_;
- uint64_t decommit_free_block_threshold_, decommit_total_free_threshold_;
- uint64_t lock_prefix_table_va_;
- uint64_t max_allocation_size_;
- uint64_t virtual_memory_threshold_;
- uint64_t process_affinity_mask_;
- uint32_t process_heap_flags_;
- uint16_t service_pack_version_;
- uint64_t edit_list_va_;
- uint64_t security_cookie_va_;
- uint64_t se_handler_table_va_;
- uint64_t se_handler_count_;
-
- se_handler_list se_handlers_;
- lock_prefix_rva_list lock_prefixes_;
-};
-
-//Returns image config info
-//If image does not have config info, throws an exception
-const image_config_info get_image_config(const pe_base& pe);
-
-template<typename PEClassType>
-const image_config_info get_image_config_base(const pe_base& pe);
-
-
-//Image config directory rebuilder
-//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped
-//If write_se_handlers = true, SE Handlers list will be written just after image config directory structure
-//If write_lock_prefixes = true, Lock Prefixes address list will be written just after image config directory structure
-const image_directory rebuild_image_config(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start = 0, bool write_se_handlers = true, bool write_lock_prefixes = true, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-
-template<typename PEClassType>
-const image_directory rebuild_image_config_base(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start = 0, bool write_se_handlers = true, bool write_lock_prefixes = true, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-}
diff --git a/tools/pe_bliss/pe_properties.cpp b/tools/pe_bliss/pe_properties.cpp
deleted file mode 100644
index 8d1c2eac43..0000000000
--- a/tools/pe_bliss/pe_properties.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_properties.h"
-
-namespace pe_bliss
-{
-//Destructor
-pe_properties::~pe_properties()
-{}
-
-//Clears PE characteristics flag
-void pe_properties::clear_characteristics_flags(uint16_t flags)
-{
- set_characteristics(get_characteristics() & ~flags);
-}
-
-//Sets PE characteristics flag
-void pe_properties::set_characteristics_flags(uint16_t flags)
-{
- set_characteristics(get_characteristics() | flags);
-}
-}
diff --git a/tools/pe_bliss/pe_properties.h b/tools/pe_bliss/pe_properties.h
deleted file mode 100644
index 1db163e8b1..0000000000
--- a/tools/pe_bliss/pe_properties.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <memory>
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-class pe_properties
-{
-public: //Constructors
- virtual std::auto_ptr<pe_properties> duplicate() const = 0;
-
- //Fills properly PE structures
- virtual void create_pe(uint32_t section_alignment, uint16_t subsystem) = 0;
-
-public:
- //Destructor
- virtual ~pe_properties();
-
-
-public: //DIRECTORIES
- //Returns true if directory exists
- virtual bool directory_exists(uint32_t id) const = 0;
-
- //Removes directory
- virtual void remove_directory(uint32_t id) = 0;
-
- //Returns directory RVA
- virtual uint32_t get_directory_rva(uint32_t id) const = 0;
- //Returns directory size
- virtual uint32_t get_directory_size(uint32_t id) const = 0;
-
- //Sets directory RVA (just a value of PE header, no moving occurs)
- virtual void set_directory_rva(uint32_t id, uint32_t rva) = 0;
- //Sets directory size (just a value of PE header, no moving occurs)
- virtual void set_directory_size(uint32_t id, uint32_t size) = 0;
-
- //Strips only zero DATA_DIRECTORY entries to count = min_count
- //Returns resulting number of data directories
- //strip_iat_directory - if true, even not empty IAT directory will be stripped
- virtual uint32_t strip_data_directories(uint32_t min_count = 1, bool strip_iat_directory = true) = 0;
-
-
-public: //IMAGE
- //Returns PE type of this image
- virtual pe_type get_pe_type() const = 0;
-
-
-public: //PE HEADER
- //Returns image base for PE32 and PE64 respectively
- virtual uint32_t get_image_base_32() const = 0;
- virtual uint64_t get_image_base_64() const = 0;
-
- //Sets new image base for PE32
- virtual void set_image_base(uint32_t base) = 0;
- //Sets new image base for PE32/PE+
- virtual void set_image_base_64(uint64_t base) = 0;
-
- //Returns image entry point
- virtual uint32_t get_ep() const = 0;
- //Sets image entry point
- virtual void set_ep(uint32_t new_ep) = 0;
-
- //Returns file alignment
- virtual uint32_t get_file_alignment() const = 0;
- //Returns section alignment
- virtual uint32_t get_section_alignment() const = 0;
-
- //Sets heap size commit for PE32 and PE64 respectively
- virtual void set_heap_size_commit(uint32_t size) = 0;
- virtual void set_heap_size_commit(uint64_t size) = 0;
- //Sets heap size reserve for PE32 and PE64 respectively
- virtual void set_heap_size_reserve(uint32_t size) = 0;
- virtual void set_heap_size_reserve(uint64_t size) = 0;
- //Sets stack size commit for PE32 and PE64 respectively
- virtual void set_stack_size_commit(uint32_t size) = 0;
- virtual void set_stack_size_commit(uint64_t size) = 0;
- //Sets stack size reserve for PE32 and PE64 respectively
- virtual void set_stack_size_reserve(uint32_t size) = 0;
- virtual void set_stack_size_reserve(uint64_t size) = 0;
-
- //Returns heap size commit for PE32 and PE64 respectively
- virtual uint32_t get_heap_size_commit_32() const = 0;
- virtual uint64_t get_heap_size_commit_64() const = 0;
- //Returns heap size reserve for PE32 and PE64 respectively
- virtual uint32_t get_heap_size_reserve_32() const = 0;
- virtual uint64_t get_heap_size_reserve_64() const = 0;
- //Returns stack size commit for PE32 and PE64 respectively
- virtual uint32_t get_stack_size_commit_32() const = 0;
- virtual uint64_t get_stack_size_commit_64() const = 0;
- //Returns stack size reserve for PE32 and PE64 respectively
- virtual uint32_t get_stack_size_reserve_32() const = 0;
- virtual uint64_t get_stack_size_reserve_64() const = 0;
-
- //Returns virtual size of image
- virtual uint32_t get_size_of_image() const = 0;
-
- //Returns number of RVA and sizes (number of DATA_DIRECTORY entries)
- virtual uint32_t get_number_of_rvas_and_sizes() const = 0;
- //Sets number of RVA and sizes (number of DATA_DIRECTORY entries)
- virtual void set_number_of_rvas_and_sizes(uint32_t number) = 0;
-
- //Returns PE characteristics
- virtual uint16_t get_characteristics() const = 0;
- //Sets PE characteristics
- virtual void set_characteristics(uint16_t ch) = 0;
-
- //Clears PE characteristics flag
- void clear_characteristics_flags(uint16_t flags);
- //Sets PE characteristics flag
- void set_characteristics_flags(uint16_t flags);
-
- //Returns size of headers
- virtual uint32_t get_size_of_headers() const = 0;
-
- //Returns subsystem
- virtual uint16_t get_subsystem() const = 0;
-
- //Sets subsystem
- virtual void set_subsystem(uint16_t subsystem) = 0;
-
- //Returns size of optional header
- virtual uint16_t get_size_of_optional_header() const = 0;
-
- //Returns PE signature
- virtual uint32_t get_pe_signature() const = 0;
-
- //Returns PE magic value
- virtual uint32_t get_magic() const = 0;
-
- //Returns checksum of PE file from header
- virtual uint32_t get_checksum() const = 0;
-
- //Sets checksum of PE file
- virtual void set_checksum(uint32_t checksum) = 0;
-
- //Returns timestamp of PE file from header
- virtual uint32_t get_time_date_stamp() const = 0;
-
- //Sets timestamp of PE file
- virtual void set_time_date_stamp(uint32_t timestamp) = 0;
-
- //Returns Machine field value of PE file from header
- virtual uint16_t get_machine() const = 0;
-
- //Sets Machine field value of PE file
- virtual void set_machine(uint16_t machine) = 0;
-
- //Returns DLL Characteristics
- virtual uint16_t get_dll_characteristics() const = 0;
-
- //Sets DLL Characteristics
- virtual void set_dll_characteristics(uint16_t characteristics) = 0;
-
- //Sets required operation system version
- virtual void set_os_version(uint16_t major, uint16_t minor) = 0;
-
- //Returns required operation system version (minor word)
- virtual uint16_t get_minor_os_version() const = 0;
-
- //Returns required operation system version (major word)
- virtual uint16_t get_major_os_version() const = 0;
-
- //Sets required subsystem version
- virtual void set_subsystem_version(uint16_t major, uint16_t minor) = 0;
-
- //Returns required subsystem version (minor word)
- virtual uint16_t get_minor_subsystem_version() const = 0;
-
- //Returns required subsystem version (major word)
- virtual uint16_t get_major_subsystem_version() const = 0;
-
-public: //ADDRESS CONVERTIONS
- //Virtual Address (VA) to Relative Virtual Address (RVA) convertions
- //for PE32 and PE64 respectively
- //bound_check checks integer overflow
- virtual uint32_t va_to_rva(uint32_t va, bool bound_check = true) const = 0;
- virtual uint32_t va_to_rva(uint64_t va, bool bound_check = true) const = 0;
-
- //Relative Virtual Address (RVA) to Virtual Address (VA) convertions
- //for PE32 and PE64 respectively
- virtual uint32_t rva_to_va_32(uint32_t rva) const = 0;
- virtual uint64_t rva_to_va_64(uint32_t rva) const = 0;
-
-
-public: //SECTIONS
- //Returns number of sections
- virtual uint16_t get_number_of_sections() const = 0;
-
-public:
- //Sets number of sections
- virtual void set_number_of_sections(uint16_t number) = 0;
- //Sets virtual size of image
- virtual void set_size_of_image(uint32_t size) = 0;
- //Sets size of headers
- virtual void set_size_of_headers(uint32_t size) = 0;
- //Sets size of optional headers
- virtual void set_size_of_optional_header(uint16_t size) = 0;
- //Returns nt headers data pointer
- virtual char* get_nt_headers_ptr() = 0;
- //Returns nt headers data pointer
- virtual const char* get_nt_headers_ptr() const = 0;
- //Returns size of NT header
- virtual uint32_t get_sizeof_nt_header() const = 0;
- //Returns size of optional headers
- virtual uint32_t get_sizeof_opt_headers() const = 0;
- //Sets file alignment (no checks)
- virtual void set_file_alignment_unchecked(uint32_t alignment) = 0;
- //Sets base of code
- virtual void set_base_of_code(uint32_t base) = 0;
- //Returns base of code
- virtual uint32_t get_base_of_code() const = 0;
- //Returns needed PE magic for PE or PE+ (from template parameters)
- virtual uint32_t get_needed_magic() const = 0;
-};
-}
diff --git a/tools/pe_bliss/pe_properties_generic.cpp b/tools/pe_bliss/pe_properties_generic.cpp
deleted file mode 100644
index bcf6f2047d..0000000000
--- a/tools/pe_bliss/pe_properties_generic.cpp
+++ /dev/null
@@ -1,645 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "pe_properties_generic.h"
-#include "pe_exception.h"
-#include "utils.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Constructor
-template<typename PEClassType>
-std::auto_ptr<pe_properties> pe_properties_generic<PEClassType>::duplicate() const
-{
- return std::auto_ptr<pe_properties>(new pe_properties_generic<PEClassType>(*this));
-}
-
-//Fills properly PE structures
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::create_pe(uint32_t section_alignment, uint16_t subsystem)
-{
- memset(&nt_headers_, 0, sizeof(nt_headers_));
- nt_headers_.Signature = 0x4550; //"PE"
- nt_headers_.FileHeader.Machine = 0x14C; //i386
- nt_headers_.FileHeader.SizeOfOptionalHeader = sizeof(nt_headers_.OptionalHeader);
- nt_headers_.OptionalHeader.Magic = PEClassType::Id;
- nt_headers_.OptionalHeader.ImageBase = 0x400000;
- nt_headers_.OptionalHeader.SectionAlignment = section_alignment;
- nt_headers_.OptionalHeader.FileAlignment = 0x200;
- nt_headers_.OptionalHeader.SizeOfHeaders = 1024;
- nt_headers_.OptionalHeader.Subsystem = subsystem;
- nt_headers_.OptionalHeader.SizeOfHeapReserve = 0x100000;
- nt_headers_.OptionalHeader.SizeOfHeapCommit = 0x1000;
- nt_headers_.OptionalHeader.SizeOfStackReserve = 0x100000;
- nt_headers_.OptionalHeader.SizeOfStackCommit = 0x1000;
- nt_headers_.OptionalHeader.NumberOfRvaAndSizes = 0x10;
-}
-
-//Duplicate
-template<typename PEClassType>
-pe_properties_generic<PEClassType>::~pe_properties_generic()
-{}
-
-//Returns true if directory exists
-template<typename PEClassType>
-bool pe_properties_generic<PEClassType>::directory_exists(uint32_t id) const
-{
- return (nt_headers_.OptionalHeader.NumberOfRvaAndSizes - 1) >= id &&
- nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress;
-}
-
-//Removes directory
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::remove_directory(uint32_t id)
-{
- if(directory_exists(id))
- {
- nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress = 0;
- nt_headers_.OptionalHeader.DataDirectory[id].Size = 0;
-
- if(id == image_directory_entry_basereloc)
- {
- set_characteristics_flags(image_file_relocs_stripped);
- set_dll_characteristics(get_dll_characteristics() & ~image_dllcharacteristics_dynamic_base);
- }
- else if(id == image_directory_entry_export)
- {
- clear_characteristics_flags(image_file_dll);
- }
- }
-}
-
-//Returns directory RVA
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_directory_rva(uint32_t id) const
-{
- //Check if directory exists
- if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id)
- throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist);
-
- return nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress;
-}
-
-//Returns directory size
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_directory_rva(uint32_t id, uint32_t va)
-{
- //Check if directory exists
- if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id)
- throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist);
-
- nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress = va;
-}
-
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_directory_size(uint32_t id, uint32_t size)
-{
- //Check if directory exists
- if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id)
- throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist);
-
- nt_headers_.OptionalHeader.DataDirectory[id].Size = size;
-}
-
-//Returns directory size
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_directory_size(uint32_t id) const
-{
- //Check if directory exists
- if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id)
- throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist);
-
- return nt_headers_.OptionalHeader.DataDirectory[id].Size;
-}
-
-//Strips only zero DATA_DIRECTORY entries to count = min_count
-//Returns resulting number of data directories
-//strip_iat_directory - if true, even not empty IAT directory will be stripped
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::strip_data_directories(uint32_t min_count, bool strip_iat_directory)
-{
- int i = nt_headers_.OptionalHeader.NumberOfRvaAndSizes - 1;
-
- //Enumerate all data directories from the end
- for(; i >= 0; i--)
- {
- //If directory exists, break
- if(nt_headers_.OptionalHeader.DataDirectory[i].VirtualAddress && (static_cast<uint32_t>(i) != image_directory_entry_iat || !strip_iat_directory))
- break;
-
- if(i <= static_cast<int>(min_count) - 2)
- break;
- }
-
- if(i == image_numberof_directory_entries - 1)
- return image_numberof_directory_entries;
-
- //Return new number of data directories
- return nt_headers_.OptionalHeader.NumberOfRvaAndSizes = i + 1;
-}
-
-//Returns image base for PE32
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_image_base_32() const
-{
- return static_cast<uint32_t>(nt_headers_.OptionalHeader.ImageBase);
-}
-
-//Returns image base for PE32/PE64
-template<typename PEClassType>
-uint64_t pe_properties_generic<PEClassType>::get_image_base_64() const
-{
- return static_cast<uint64_t>(nt_headers_.OptionalHeader.ImageBase);
-}
-
-//Sets new image base
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_image_base(uint32_t base)
-{
- nt_headers_.OptionalHeader.ImageBase = base;
-}
-
-//Sets new image base
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_image_base_64(uint64_t base)
-{
- nt_headers_.OptionalHeader.ImageBase = static_cast<typename PEClassType::BaseSize>(base);
-}
-
-//Returns image entry point
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_ep() const
-{
- return nt_headers_.OptionalHeader.AddressOfEntryPoint;
-}
-
-//Sets image entry point
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_ep(uint32_t new_ep)
-{
- nt_headers_.OptionalHeader.AddressOfEntryPoint = new_ep;
-}
-
-//Returns file alignment
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_file_alignment() const
-{
- return nt_headers_.OptionalHeader.FileAlignment;
-}
-
-//Returns section alignment
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_section_alignment() const
-{
- return nt_headers_.OptionalHeader.SectionAlignment;
-}
-
-//Sets heap size commit for PE32
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_heap_size_commit(uint32_t size)
-{
- nt_headers_.OptionalHeader.SizeOfHeapCommit = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Sets heap size commit for PE32/PE64
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_heap_size_commit(uint64_t size)
-{
- nt_headers_.OptionalHeader.SizeOfHeapCommit = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Sets heap size reserve for PE32
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_heap_size_reserve(uint32_t size)
-{
- nt_headers_.OptionalHeader.SizeOfHeapReserve = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Sets heap size reserve for PE32/PE64
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_heap_size_reserve(uint64_t size)
-{
- nt_headers_.OptionalHeader.SizeOfHeapReserve = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Sets stack size commit for PE32
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_stack_size_commit(uint32_t size)
-{
- nt_headers_.OptionalHeader.SizeOfStackCommit = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Sets stack size commit for PE32/PE64
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_stack_size_commit(uint64_t size)
-{
- nt_headers_.OptionalHeader.SizeOfStackCommit = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Sets stack size reserve for PE32
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_stack_size_reserve(uint32_t size)
-{
- nt_headers_.OptionalHeader.SizeOfStackReserve = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Sets stack size reserve for PE32/PE64
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_stack_size_reserve(uint64_t size)
-{
- nt_headers_.OptionalHeader.SizeOfStackReserve = static_cast<typename PEClassType::BaseSize>(size);
-}
-
-//Returns heap size commit for PE32
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_heap_size_commit_32() const
-{
- return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfHeapCommit);
-}
-
-//Returns heap size commit for PE32/PE64
-template<typename PEClassType>
-uint64_t pe_properties_generic<PEClassType>::get_heap_size_commit_64() const
-{
- return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfHeapCommit);
-}
-
-//Returns heap size reserve for PE32
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_heap_size_reserve_32() const
-{
- return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfHeapReserve);
-}
-
-//Returns heap size reserve for PE32/PE64
-template<typename PEClassType>
-uint64_t pe_properties_generic<PEClassType>::get_heap_size_reserve_64() const
-{
- return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfHeapReserve);
-}
-
-//Returns stack size commit for PE32
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_stack_size_commit_32() const
-{
- return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfStackCommit);
-}
-
-//Returns stack size commit for PE32/PE64
-template<typename PEClassType>
-uint64_t pe_properties_generic<PEClassType>::get_stack_size_commit_64() const
-{
- return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfStackCommit);
-}
-
-//Returns stack size reserve for PE32
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_stack_size_reserve_32() const
-{
- return static_cast<uint32_t>(nt_headers_.OptionalHeader.SizeOfStackReserve);
-}
-
-//Returns stack size reserve for PE32/PE64
-template<typename PEClassType>
-uint64_t pe_properties_generic<PEClassType>::get_stack_size_reserve_64() const
-{
- return static_cast<uint64_t>(nt_headers_.OptionalHeader.SizeOfStackReserve);
-}
-
-//Returns virtual size of image
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_size_of_image() const
-{
- return nt_headers_.OptionalHeader.SizeOfImage;
-}
-
-//Returns number of RVA and sizes (number of DATA_DIRECTORY entries)
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_number_of_rvas_and_sizes() const
-{
- return nt_headers_.OptionalHeader.NumberOfRvaAndSizes;
-}
-
-//Sets number of RVA and sizes (number of DATA_DIRECTORY entries)
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_number_of_rvas_and_sizes(uint32_t number)
-{
- nt_headers_.OptionalHeader.NumberOfRvaAndSizes = number;
-}
-
-//Returns PE characteristics
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_characteristics() const
-{
- return nt_headers_.FileHeader.Characteristics;
-}
-
-//Returns checksum of PE file from header
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_checksum() const
-{
- return nt_headers_.OptionalHeader.CheckSum;
-}
-
-//Sets checksum of PE file
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_checksum(uint32_t checksum)
-{
- nt_headers_.OptionalHeader.CheckSum = checksum;
-}
-
-//Returns DLL Characteristics
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_dll_characteristics() const
-{
- return nt_headers_.OptionalHeader.DllCharacteristics;
-}
-
-//Returns timestamp of PE file from header
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_time_date_stamp() const
-{
- return nt_headers_.FileHeader.TimeDateStamp;
-}
-
-//Sets timestamp of PE file
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_time_date_stamp(uint32_t timestamp)
-{
- nt_headers_.FileHeader.TimeDateStamp = timestamp;
-}
-
-//Sets DLL Characteristics
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_dll_characteristics(uint16_t characteristics)
-{
- nt_headers_.OptionalHeader.DllCharacteristics = characteristics;
-}
-
-//Returns Machine field value of PE file from header
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_machine() const
-{
- return nt_headers_.FileHeader.Machine;
-}
-
-//Sets Machine field value of PE file
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_machine(uint16_t machine)
-{
- nt_headers_.FileHeader.Machine = machine;
-}
-
-//Sets PE characteristics
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_characteristics(uint16_t ch)
-{
- nt_headers_.FileHeader.Characteristics = ch;
-}
-
-//Returns size of headers
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_size_of_headers() const
-{
- return nt_headers_.OptionalHeader.SizeOfHeaders;
-}
-
-//Returns subsystem
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_subsystem() const
-{
- return nt_headers_.OptionalHeader.Subsystem;
-}
-
-//Sets subsystem
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_subsystem(uint16_t subsystem)
-{
- nt_headers_.OptionalHeader.Subsystem = subsystem;
-}
-
-//Returns size of optional header
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_size_of_optional_header() const
-{
- return nt_headers_.FileHeader.SizeOfOptionalHeader;
-}
-
-//Returns PE signature
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_pe_signature() const
-{
- return nt_headers_.Signature;
-}
-
-//Returns PE magic value
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_magic() const
-{
- return nt_headers_.OptionalHeader.Magic;
-}
-
-//Sets required operation system version
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_os_version(uint16_t major, uint16_t minor)
-{
- nt_headers_.OptionalHeader.MinorOperatingSystemVersion = minor;
- nt_headers_.OptionalHeader.MajorOperatingSystemVersion = major;
-}
-
-//Returns required operation system version (minor word)
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_minor_os_version() const
-{
- return nt_headers_.OptionalHeader.MinorOperatingSystemVersion;
-}
-
-//Returns required operation system version (major word)
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_major_os_version() const
-{
- return nt_headers_.OptionalHeader.MajorOperatingSystemVersion;
-}
-
-//Sets required subsystem version
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_subsystem_version(uint16_t major, uint16_t minor)
-{
- nt_headers_.OptionalHeader.MinorSubsystemVersion = minor;
- nt_headers_.OptionalHeader.MajorSubsystemVersion = major;
-}
-
-//Returns required subsystem version (minor word)
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_minor_subsystem_version() const
-{
- return nt_headers_.OptionalHeader.MinorSubsystemVersion;
-}
-
-//Returns required subsystem version (major word)
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_major_subsystem_version() const
-{
- return nt_headers_.OptionalHeader.MajorSubsystemVersion;
-}
-
-//Virtual Address (VA) to Relative Virtual Address (RVA) convertions for PE32
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::va_to_rva(uint32_t va, bool bound_check) const
-{
- if(bound_check && static_cast<uint64_t>(va) - nt_headers_.OptionalHeader.ImageBase > pe_utils::max_dword)
- throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion);
-
- return static_cast<uint32_t>(va - nt_headers_.OptionalHeader.ImageBase);
-}
-
-//Virtual Address (VA) to Relative Virtual Address (RVA) convertions for PE32/PE64
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::va_to_rva(uint64_t va, bool bound_check) const
-{
- if(bound_check && va - nt_headers_.OptionalHeader.ImageBase > pe_utils::max_dword)
- throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion);
-
- return static_cast<uint32_t>(va - nt_headers_.OptionalHeader.ImageBase);
-}
-
-//Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::rva_to_va_32(uint32_t rva) const
-{
- if(!pe_utils::is_sum_safe(rva, static_cast<uint32_t>(nt_headers_.OptionalHeader.ImageBase)))
- throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion);
-
- return static_cast<uint32_t>(rva + nt_headers_.OptionalHeader.ImageBase);
-}
-
-//Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32/PE64
-template<typename PEClassType>
-uint64_t pe_properties_generic<PEClassType>::rva_to_va_64(uint32_t rva) const
-{
- return static_cast<uint64_t>(rva) + nt_headers_.OptionalHeader.ImageBase;
-}
-
-//Returns number of sections
-template<typename PEClassType>
-uint16_t pe_properties_generic<PEClassType>::get_number_of_sections() const
-{
- return nt_headers_.FileHeader.NumberOfSections;
-}
-
-//Sets number of sections
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_number_of_sections(uint16_t number)
-{
- nt_headers_.FileHeader.NumberOfSections = number;
-}
-
-//Sets virtual size of image
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_size_of_image(uint32_t size)
-{
- nt_headers_.OptionalHeader.SizeOfImage = size;
-}
-
-//Sets size of headers
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_size_of_headers(uint32_t size)
-{
- nt_headers_.OptionalHeader.SizeOfHeaders = size;
-}
-
-//Sets size of optional headers
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_size_of_optional_header(uint16_t size)
-{
- nt_headers_.FileHeader.SizeOfOptionalHeader = size;
-}
-
-//Returns nt headers data pointer
-template<typename PEClassType>
-char* pe_properties_generic<PEClassType>::get_nt_headers_ptr()
-{
- return reinterpret_cast<char*>(&nt_headers_);
-}
-
-//Returns nt headers data pointer
-template<typename PEClassType>
-const char* pe_properties_generic<PEClassType>::get_nt_headers_ptr() const
-{
- return reinterpret_cast<const char*>(&nt_headers_);
-}
-
-//Returns size of NT header
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_sizeof_nt_header() const
-{
- return sizeof(typename PEClassType::NtHeaders);
-}
-
-//Returns size of optional headers
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_sizeof_opt_headers() const
-{
- return sizeof(typename PEClassType::OptHeaders);
-}
-
-//Sets file alignment (no checks)
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_file_alignment_unchecked(uint32_t alignment)
-{
- nt_headers_.OptionalHeader.FileAlignment = alignment;
-}
-
-//Sets base of code
-template<typename PEClassType>
-void pe_properties_generic<PEClassType>::set_base_of_code(uint32_t base)
-{
- nt_headers_.OptionalHeader.BaseOfCode = base;
-}
-
-//Returns base of code
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_base_of_code() const
-{
- return nt_headers_.OptionalHeader.BaseOfCode;
-}
-
-//Returns needed PE magic for PE or PE+ (from template parameters)
-template<typename PEClassType>
-uint32_t pe_properties_generic<PEClassType>::get_needed_magic() const
-{
- return PEClassType::Id;
-}
-
-//Returns PE type of this image
-template<typename PEClassType>
-pe_type pe_properties_generic<PEClassType>::get_pe_type() const
-{
- return PEClassType::Id == image_nt_optional_hdr32_magic ? pe_type_32 : pe_type_64;
-}
-
-//Two used instantiations for PE32 (PE) and PE64 (PE+)
-template class pe_properties_generic<pe_types_class_32>;
-template class pe_properties_generic<pe_types_class_64>;
-}
diff --git a/tools/pe_bliss/pe_properties_generic.h b/tools/pe_bliss/pe_properties_generic.h
deleted file mode 100644
index 4ff906803c..0000000000
--- a/tools/pe_bliss/pe_properties_generic.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_properties.h"
-
-namespace pe_bliss
-{
-//Helper class to reduce code size and ease its editing
-template<
- typename NtHeadersType,
- typename OptHeadersType,
- uint16_t IdVal,
- typename BaseSizeType,
- BaseSizeType ImportSnapFlagVal,
- typename TLSStructType,
- typename ConfigStructType>
-class pe_types
-{
-public:
- typedef NtHeadersType NtHeaders; //NT HEADERS type
- typedef OptHeadersType OptHeaders; //NT OPTIONAL HEADER type
- typedef BaseSizeType BaseSize; //Base size of different values: DWORD or ULONGLONG
- typedef TLSStructType TLSStruct; //TLS structure type
- typedef ConfigStructType ConfigStruct; //Configuration structure type
-
- static const uint16_t Id = IdVal; //Magic of PE or PE+
- static const BaseSize ImportSnapFlag = ImportSnapFlagVal; //Import snap flag value
-};
-
-//Portable Executable derived class for PE and PE+
-//Describes PE/PE+ dependent things
-template<typename PEClassType>
-class pe_properties_generic : public pe_properties
-{
-public: //Constructor
- virtual std::auto_ptr<pe_properties> duplicate() const;
-
- //Fills properly PE structures
- virtual void create_pe(uint32_t section_alignment, uint16_t subsystem);
-
-public:
- //Destructor
- virtual ~pe_properties_generic();
-
-
-public: //DIRECTORIES
- //Returns true if directory exists
- virtual bool directory_exists(uint32_t id) const;
-
- //Removes directory
- virtual void remove_directory(uint32_t id);
-
- //Returns directory RVA
- virtual uint32_t get_directory_rva(uint32_t id) const;
- //Returns directory size
- virtual uint32_t get_directory_size(uint32_t id) const;
-
- //Sets directory RVA (just a value of PE header, no moving occurs)
- virtual void set_directory_rva(uint32_t id, uint32_t rva);
- //Sets directory size (just a value of PE header, no moving occurs)
- virtual void set_directory_size(uint32_t id, uint32_t size);
-
- //Strips only zero DATA_DIRECTORY entries to count = min_count
- //Returns resulting number of data directories
- //strip_iat_directory - if true, even not empty IAT directory will be stripped
- virtual uint32_t strip_data_directories(uint32_t min_count = 1, bool strip_iat_directory = true);
-
-
-public: //IMAGE
- //Returns PE type of this image
- virtual pe_type get_pe_type() const;
-
-
-public: //PE HEADER
- //Returns image base for PE32 and PE64 respectively
- virtual uint32_t get_image_base_32() const;
- virtual uint64_t get_image_base_64() const;
-
- //Sets new image base for PE32
- virtual void set_image_base(uint32_t base);
- //Sets new image base for PE32/PE+
- virtual void set_image_base_64(uint64_t base);
-
- //Returns image entry point
- virtual uint32_t get_ep() const;
- //Sets image entry point
- virtual void set_ep(uint32_t new_ep);
-
- //Returns file alignment
- virtual uint32_t get_file_alignment() const;
- //Returns section alignment
- virtual uint32_t get_section_alignment() const;
-
- //Sets heap size commit for PE32 and PE64 respectively
- virtual void set_heap_size_commit(uint32_t size);
- virtual void set_heap_size_commit(uint64_t size);
- //Sets heap size reserve for PE32 and PE64 respectively
- virtual void set_heap_size_reserve(uint32_t size);
- virtual void set_heap_size_reserve(uint64_t size);
- //Sets stack size commit for PE32 and PE64 respectively
- virtual void set_stack_size_commit(uint32_t size);
- virtual void set_stack_size_commit(uint64_t size);
- //Sets stack size reserve for PE32 and PE64 respectively
- virtual void set_stack_size_reserve(uint32_t size);
- virtual void set_stack_size_reserve(uint64_t size);
-
- //Returns heap size commit for PE32 and PE64 respectively
- virtual uint32_t get_heap_size_commit_32() const;
- virtual uint64_t get_heap_size_commit_64() const;
- //Returns heap size reserve for PE32 and PE64 respectively
- virtual uint32_t get_heap_size_reserve_32() const;
- virtual uint64_t get_heap_size_reserve_64() const;
- //Returns stack size commit for PE32 and PE64 respectively
- virtual uint32_t get_stack_size_commit_32() const;
- virtual uint64_t get_stack_size_commit_64() const;
- //Returns stack size reserve for PE32 and PE64 respectively
- virtual uint32_t get_stack_size_reserve_32() const;
- virtual uint64_t get_stack_size_reserve_64() const;
-
- //Returns virtual size of image
- virtual uint32_t get_size_of_image() const;
-
- //Returns number of RVA and sizes (number of DATA_DIRECTORY entries)
- virtual uint32_t get_number_of_rvas_and_sizes() const;
- //Sets number of RVA and sizes (number of DATA_DIRECTORY entries)
- virtual void set_number_of_rvas_and_sizes(uint32_t number);
-
- //Returns PE characteristics
- virtual uint16_t get_characteristics() const;
- //Sets PE characteristics
- virtual void set_characteristics(uint16_t ch);
-
- //Returns size of headers
- virtual uint32_t get_size_of_headers() const;
-
- //Returns subsystem
- virtual uint16_t get_subsystem() const;
-
- //Sets subsystem
- virtual void set_subsystem(uint16_t subsystem);
-
- //Returns size of optional header
- virtual uint16_t get_size_of_optional_header() const;
-
- //Returns PE signature
- virtual uint32_t get_pe_signature() const;
-
- //Returns PE magic value
- virtual uint32_t get_magic() const;
-
- //Returns checksum of PE file from header
- virtual uint32_t get_checksum() const;
-
- //Sets checksum of PE file
- virtual void set_checksum(uint32_t checksum);
-
- //Returns timestamp of PE file from header
- virtual uint32_t get_time_date_stamp() const;
-
- //Sets timestamp of PE file
- virtual void set_time_date_stamp(uint32_t timestamp);
-
- //Returns Machine field value of PE file from header
- virtual uint16_t get_machine() const;
-
- //Sets Machine field value of PE file
- virtual void set_machine(uint16_t machine);
-
- //Returns DLL Characteristics
- virtual uint16_t get_dll_characteristics() const;
-
- //Sets DLL Characteristics
- virtual void set_dll_characteristics(uint16_t characteristics);
-
- //Sets required operation system version
- virtual void set_os_version(uint16_t major, uint16_t minor);
-
- //Returns required operation system version (minor word)
- virtual uint16_t get_minor_os_version() const;
-
- //Returns required operation system version (major word)
- virtual uint16_t get_major_os_version() const;
-
- //Sets required subsystem version
- virtual void set_subsystem_version(uint16_t major, uint16_t minor);
-
- //Returns required subsystem version (minor word)
- virtual uint16_t get_minor_subsystem_version() const;
-
- //Returns required subsystem version (major word)
- virtual uint16_t get_major_subsystem_version() const;
-
-public: //ADDRESS CONVERTIONS
- //Virtual Address (VA) to Relative Virtual Address (RVA) convertions
- //for PE32 and PE64 respectively
- //bound_check checks integer overflow
- virtual uint32_t va_to_rva(uint32_t va, bool bound_check = true) const;
- virtual uint32_t va_to_rva(uint64_t va, bool bound_check = true) const;
-
- //Relative Virtual Address (RVA) to Virtual Address (VA) convertions
- //for PE32 and PE64 respectively
- virtual uint32_t rva_to_va_32(uint32_t rva) const;
- virtual uint64_t rva_to_va_64(uint32_t rva) const;
-
-
-public: //SECTIONS
- //Returns number of sections
- virtual uint16_t get_number_of_sections() const;
-
-protected:
- typename PEClassType::NtHeaders nt_headers_; //NT headers (PE32 or PE64)
-
-public:
- //Sets number of sections
- virtual void set_number_of_sections(uint16_t number);
- //Sets virtual size of image
- virtual void set_size_of_image(uint32_t size);
- //Sets size of headers
- virtual void set_size_of_headers(uint32_t size);
- //Sets size of optional headers
- virtual void set_size_of_optional_header(uint16_t size);
- //Returns nt headers data pointer
- virtual char* get_nt_headers_ptr();
- //Returns nt headers data pointer
- virtual const char* get_nt_headers_ptr() const;
- //Returns size of NT header
- virtual uint32_t get_sizeof_nt_header() const;
- //Returns size of optional headers
- virtual uint32_t get_sizeof_opt_headers() const;
- //Sets file alignment (no checks)
- virtual void set_file_alignment_unchecked(uint32_t alignment);
- //Sets base of code
- virtual void set_base_of_code(uint32_t base);
- //Returns base of code
- virtual uint32_t get_base_of_code() const;
- //Returns needed PE magic for PE or PE+ (from template parameters)
- virtual uint32_t get_needed_magic() const;
-};
-
-//Two used typedefs for PE32 (PE) and PE64 (PE+)
-typedef pe_types<pe_win::image_nt_headers32,
- pe_win::image_optional_header32,
- pe_win::image_nt_optional_hdr32_magic,
- uint32_t,
- pe_win::image_ordinal_flag32,
- pe_win::image_tls_directory32,
- pe_win::image_load_config_directory32> pe_types_class_32;
-
-typedef pe_types<pe_win::image_nt_headers64,
- pe_win::image_optional_header64,
- pe_win::image_nt_optional_hdr64_magic,
- uint64_t,
- pe_win::image_ordinal_flag64,
- pe_win::image_tls_directory64,
- pe_win::image_load_config_directory64> pe_types_class_64;
-
-typedef pe_properties_generic<pe_types_class_32> pe_properties_32;
-typedef pe_properties_generic<pe_types_class_64> pe_properties_64;
-}
diff --git a/tools/pe_bliss/pe_rebuilder.cpp b/tools/pe_bliss/pe_rebuilder.cpp
deleted file mode 100644
index faf5803b8c..0000000000
--- a/tools/pe_bliss/pe_rebuilder.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_rebuilder.h"
-#include "pe_base.h"
-#include "pe_structures.h"
-#include "pe_exception.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Rebuilds PE image headers
-//If strip_dos_header is true, DOS headers partially will be used for PE headers
-//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically
-//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers)
-void rebuild_pe(pe_base& pe, image_dos_header& dos_header, bool strip_dos_header, bool change_size_of_headers, bool save_bound_import)
-{
- dos_header = pe.get_dos_header();
-
- if(strip_dos_header)
- {
- //Strip stub overlay
- pe.strip_stub_overlay();
- //BaseOfCode NT Headers field now overlaps
- //e_lfanew field, so we're acrually setting
- //e_lfanew with this call
- pe.set_base_of_code(8 * sizeof(uint16_t));
- }
- else
- {
- //Set start of PE headers
- dos_header.e_lfanew = sizeof(image_dos_header)
- + pe_utils::align_up(static_cast<uint32_t>(pe.get_stub_overlay().size()), sizeof(uint32_t));
- }
-
- section_list& sections = pe.get_image_sections();
-
- //Calculate pointer to section data
- size_t ptr_to_section_data = (strip_dos_header ? 8 * sizeof(uint16_t) : sizeof(image_dos_header)) + pe.get_sizeof_nt_header()
- + pe_utils::align_up(pe.get_stub_overlay().size(), sizeof(uint32_t))
- - sizeof(image_data_directory) * (image_numberof_directory_entries - pe.get_number_of_rvas_and_sizes())
- + sections.size() * sizeof(image_section_header);
-
- if(save_bound_import && pe.has_bound_import())
- {
- //It will be aligned to DWORD, because we're aligning to DWORD everything above it
- pe.set_directory_rva(image_directory_entry_bound_import, static_cast<uint32_t>(ptr_to_section_data));
- ptr_to_section_data += pe.get_directory_size(image_directory_entry_bound_import);
- }
-
- ptr_to_section_data = pe_utils::align_up(ptr_to_section_data, pe.get_file_alignment());
-
- //Set size of headers and size of optional header
- if(change_size_of_headers)
- {
- if(!pe.get_image_sections().empty())
- {
- if(static_cast<uint32_t>(ptr_to_section_data) > (*sections.begin()).get_virtual_address())
- throw pe_exception("Headers of PE file are too long. Try to strip STUB or don't build bound import", pe_exception::cannot_rebuild_image);
- }
-
- pe.set_size_of_headers(static_cast<uint32_t>(ptr_to_section_data));
- }
-
- //Set number of sections in PE header
- pe.update_number_of_sections();
-
- pe.update_image_size();
-
- pe.set_size_of_optional_header(static_cast<uint16_t>(pe.get_sizeof_opt_headers()
- - sizeof(image_data_directory) * (image_numberof_directory_entries - pe.get_number_of_rvas_and_sizes())));
-
- //Recalculate pointer to raw data according to section list
- for(section_list::iterator it = sections.begin(); it != sections.end(); ++it)
- {
- //Save section headers PointerToRawData
- (*it).set_pointer_to_raw_data(static_cast<uint32_t>(ptr_to_section_data));
- ptr_to_section_data += (*it).get_aligned_raw_size(pe.get_file_alignment());
- }
-}
-
-//Rebuild PE image and write it to "out" ostream
-//If strip_dos_header is true, DOS headers partially will be used for PE headers
-//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically
-//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers)
-void rebuild_pe(pe_base& pe, std::ostream& out, bool strip_dos_header, bool change_size_of_headers, bool save_bound_import)
-{
- if(out.bad())
- throw pe_exception("Stream is bad", pe_exception::stream_is_bad);
-
- if(save_bound_import && pe.has_bound_import())
- {
- if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_bound_import), pe.get_directory_rva(image_directory_entry_bound_import), section_data_raw, true)
- < pe.get_directory_size(image_directory_entry_bound_import))
- throw pe_exception("Incorrect bound import directory", pe_exception::incorrect_bound_import_directory);
- }
-
- //Change ostream state
- out.exceptions(std::ios::goodbit);
- out.clear();
-
- uint32_t original_bound_import_rva = pe.has_bound_import() ? pe.get_directory_rva(image_directory_entry_bound_import) : 0;
- if(original_bound_import_rva && original_bound_import_rva > pe.get_size_of_headers())
- {
- //No need to do anything with bound import directory
- //if it is placed inside of any section, not headers
- original_bound_import_rva = 0;
- save_bound_import = false;
- }
-
- {
- image_dos_header dos_header;
-
- //Rebuild PE image headers
- rebuild_pe(pe, dos_header, strip_dos_header, change_size_of_headers, save_bound_import);
-
- //Write DOS header
- out.write(reinterpret_cast<const char*>(&dos_header), strip_dos_header ? 8 * sizeof(uint16_t) : sizeof(image_dos_header));
- }
-
- //If we have stub overlay, write it too
- {
- const std::string& stub = pe.get_stub_overlay();
- if(stub.size())
- {
- out.write(stub.data(), stub.size());
- size_t aligned_size = pe_utils::align_up(stub.size(), sizeof(uint32_t));
- //Align PE header, which is right after rich overlay
- while(aligned_size > stub.size())
- {
- out.put('\0');
- --aligned_size;
- }
- }
- }
-
- //Write NT headers
- out.write(static_cast<const pe_base&>(pe).get_nt_headers_ptr(), pe.get_sizeof_nt_header()
- - sizeof(image_data_directory) * (image_numberof_directory_entries - pe.get_number_of_rvas_and_sizes()));
-
- //Write section headers
- const section_list& sections = pe.get_image_sections();
- for(section_list::const_iterator it = sections.begin(); it != sections.end(); ++it)
- {
- if(it == sections.end() - 1) //If last section encountered
- {
- image_section_header header((*it).get_raw_header());
- header.SizeOfRawData = static_cast<uint32_t>((*it).get_raw_data().length()); //Set non-aligned actual data length for it
- out.write(reinterpret_cast<const char*>(&header), sizeof(image_section_header));
- }
- else
- {
- out.write(reinterpret_cast<const char*>(&(*it).get_raw_header()), sizeof(image_section_header));
- }
- }
-
- //Write bound import data if requested
- if(save_bound_import && pe.has_bound_import())
- {
- out.write(pe.section_data_from_rva(original_bound_import_rva, section_data_raw, true),
- pe.get_directory_size(image_directory_entry_bound_import));
- }
-
- //Write section data finally
- for(section_list::const_iterator it = sections.begin(); it != sections.end(); ++it)
- {
- const section& s = *it;
-
- std::streamoff wpos = out.tellp();
-
- //Fill unused overlay data between sections with null bytes
- for(unsigned int i = 0; i < s.get_pointer_to_raw_data() - wpos; i++)
- out.put(0);
-
- //Write raw section data
- out.write(s.get_raw_data().data(), s.get_raw_data().length());
- }
-}
-
-//Rebuild PE image and write it to "out" file
-//If strip_dos_header is true, DOS headers partially will be used for PE headers
-//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically
-//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers)
-void rebuild_pe(pe_base& pe, const char* out, bool strip_dos_header, bool change_size_of_headers, bool save_bound_import)
-{
- std::ofstream pe_file(out, std::ios::out | std::ios::binary | std::ios::trunc);
- if(!pe_file)
- {
- throw pe_exception("Error in open file.", pe_exception::stream_is_bad);
- }
- rebuild_pe(pe, pe_file, strip_dos_header, change_size_of_headers, save_bound_import);
-}
-
-
-}
diff --git a/tools/pe_bliss/pe_rebuilder.h b/tools/pe_bliss/pe_rebuilder.h
deleted file mode 100644
index 319807e5c9..0000000000
--- a/tools/pe_bliss/pe_rebuilder.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <ostream>
-#include <fstream>
-
-namespace pe_bliss
-{
-class pe_base;
-//Rebuilds PE image, writes resulting image to ostream "out". If strip_dos_header == true, DOS header will be stripped a little
-//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically
-//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers)
-void rebuild_pe(pe_base& pe, std::ostream& out, bool strip_dos_header = false, bool change_size_of_headers = true, bool save_bound_import = true);
-
-//Rebuild PE image and write it to "out" file
-//If strip_dos_header is true, DOS headers partially will be used for PE headers
-//If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically
-//If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers)
-void rebuild_pe(pe_base& pe, const char* out, bool strip_dos_header = false, bool change_size_of_headers = true, bool save_bound_import = true);
-
-}
diff --git a/tools/pe_bliss/pe_relocations.cpp b/tools/pe_bliss/pe_relocations.cpp
deleted file mode 100644
index d5357dd219..0000000000
--- a/tools/pe_bliss/pe_relocations.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "pe_relocations.h"
-#include "pe_properties_generic.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//RELOCATIONS
-//Default constructor
-relocation_entry::relocation_entry()
- :rva_(0), type_(0)
-{}
-
-//Constructor from relocation item (WORD)
-relocation_entry::relocation_entry(uint16_t relocation_value)
- :rva_(relocation_value & ((1 << 12) - 1)), type_(relocation_value >> 12)
-{}
-
-//Constructor from relative rva and relocation type
-relocation_entry::relocation_entry(uint16_t rrva, uint16_t type)
- :rva_(rrva), type_(type)
-{}
-
-//Returns RVA of relocation
-uint16_t relocation_entry::get_rva() const
-{
- return rva_;
-}
-
-//Returns type of relocation
-uint16_t relocation_entry::get_type() const
-{
- return type_;
-}
-
-//Sets RVA of relocation
-void relocation_entry::set_rva(uint16_t rva)
-{
- rva_ = rva;
-}
-
-//Sets type of relocation
-void relocation_entry::set_type(uint16_t type)
-{
- type_ = type;
-}
-
-//Returns relocation item (rrva + type)
-uint16_t relocation_entry::get_item() const
-{
- return rva_ | (type_ << 12);
-}
-
-//Sets relocation item (rrva + type)
-void relocation_entry::set_item(uint16_t item)
-{
- rva_ = item & ((1 << 12) - 1);
- type_ = item >> 12;
-}
-
-//Returns relocation list
-const relocation_table::relocation_list& relocation_table::get_relocations() const
-{
- return relocations_;
-}
-
-//Adds relocation to table
-void relocation_table::add_relocation(const relocation_entry& entry)
-{
- relocations_.push_back(entry);
-}
-
-//Default constructor
-relocation_table::relocation_table()
- :rva_(0)
-{}
-
-//Constructor from RVA of relocation table
-relocation_table::relocation_table(uint32_t rva)
- :rva_(rva)
-{}
-
-//Returns RVA of block
-uint32_t relocation_table::get_rva() const
-{
- return rva_;
-}
-
-//Sets RVA of block
-void relocation_table::set_rva(uint32_t rva)
-{
- rva_ = rva;
-}
-
-//Returns changeable relocation list
-relocation_table::relocation_list& relocation_table::get_relocations()
-{
- return relocations_;
-}
-
-//Get relocation list of pe file, supports one-word sized relocations only
-//If list_absolute_entries = true, IMAGE_REL_BASED_ABSOLUTE will be listed
-const relocation_table_list get_relocations(const pe_base& pe, bool list_absolute_entries)
-{
- relocation_table_list ret;
-
- //If image does not have relocations
- if(!pe.has_reloc())
- return ret;
-
- //Check the length in bytes of the section containing relocation directory
- if(pe.section_data_length_from_rva(pe.get_directory_rva(image_directory_entry_basereloc),
- pe.get_directory_rva(image_directory_entry_basereloc), section_data_virtual, true)
- < sizeof(image_base_relocation))
- throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory);
-
- unsigned long current_pos = pe.get_directory_rva(image_directory_entry_basereloc);
- //First IMAGE_BASE_RELOCATION table
- image_base_relocation reloc_table = pe.section_data_from_rva<image_base_relocation>(current_pos, section_data_virtual, true);
-
- if(reloc_table.SizeOfBlock % 2)
- throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory);
-
- unsigned long reloc_size = pe.get_directory_size(image_directory_entry_basereloc);
- unsigned long read_size = 0;
-
- //reloc_table.VirtualAddress is not checked (not so important)
- while(reloc_table.SizeOfBlock && read_size < reloc_size)
- {
- //Create relocation table
- relocation_table table;
- //Save RVA
- table.set_rva(reloc_table.VirtualAddress);
-
- if(!pe_utils::is_sum_safe(current_pos, reloc_table.SizeOfBlock))
- throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory);
-
- //List all relocations
- for(unsigned long i = sizeof(image_base_relocation); i < reloc_table.SizeOfBlock; i += sizeof(uint16_t))
- {
- relocation_entry entry(pe.section_data_from_rva<uint16_t>(current_pos + i, section_data_virtual, true));
- if(list_absolute_entries || entry.get_type() != image_rel_based_absolute)
- table.add_relocation(entry);
- }
-
- //Save table
- ret.push_back(table);
-
- //Go to next relocation block
- if(!pe_utils::is_sum_safe(current_pos, reloc_table.SizeOfBlock))
- throw pe_exception("Incorrect relocation directory", pe_exception::incorrect_relocation_directory);
-
- current_pos += reloc_table.SizeOfBlock;
- read_size += reloc_table.SizeOfBlock;
- reloc_table = pe.section_data_from_rva<image_base_relocation>(current_pos, section_data_virtual, true);
- }
-
- return ret;
-}
-
-//Simple relocations rebuilder
-//To keep PE file working, don't remove any of existing relocations in
-//relocation_table_list returned by a call to get_relocations() function
-//auto_strip_last_section - if true and relocations are placed in the last section, it will be automatically stripped
-//offset_from_section_start - offset from the beginning of reloc_section, where relocations data will be situated
-//If save_to_pe_header is true, PE header will be modified automatically
-const image_directory rebuild_relocations(pe_base& pe, const relocation_table_list& relocs, section& reloc_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section)
-{
- //Check that reloc_section is attached to this PE image
- if(!pe.section_attached(reloc_section))
- throw pe_exception("Relocations section must be attached to PE file", pe_exception::section_is_not_attached);
-
- uint32_t current_reloc_data_pos = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t));
-
- uint32_t needed_size = current_reloc_data_pos - offset_from_section_start; //Calculate needed size for relocation tables
- uint32_t size_delta = needed_size;
-
- uint32_t start_reloc_pos = current_reloc_data_pos;
-
- //Enumerate relocation tables
- for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it)
- {
- needed_size += static_cast<uint32_t>((*it).get_relocations().size() * sizeof(uint16_t) /* relocations */ + sizeof(image_base_relocation) /* table header */);
- //End of each table will be DWORD-aligned
- if((start_reloc_pos + needed_size - size_delta) % sizeof(uint32_t))
- needed_size += sizeof(uint16_t); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation
- }
-
- //Check if reloc_section is last one. If it's not, check if there's enough place for relocations data
- if(&reloc_section != &*(pe.get_image_sections().end() - 1) &&
- (reloc_section.empty() || pe_utils::align_up(reloc_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + current_reloc_data_pos))
- throw pe_exception("Insufficient space for relocations directory", pe_exception::insufficient_space);
-
- std::string& raw_data = reloc_section.get_raw_data();
-
- //This will be done only if reloc_section is the last section of image or for section with unaligned raw length of data
- if(raw_data.length() < needed_size + current_reloc_data_pos)
- raw_data.resize(needed_size + current_reloc_data_pos); //Expand section raw data
-
- //Enumerate relocation tables
- for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it)
- {
- //Create relocation table header
- image_base_relocation reloc;
- reloc.VirtualAddress = (*it).get_rva();
- const relocation_table::relocation_list& reloc_list = (*it).get_relocations();
- reloc.SizeOfBlock = static_cast<uint32_t>(sizeof(image_base_relocation) + sizeof(uint16_t) * reloc_list.size());
- if((reloc_list.size() * sizeof(uint16_t)) % sizeof(uint32_t)) //If we must align end of relocation table
- reloc.SizeOfBlock += sizeof(uint16_t);
-
- memcpy(&raw_data[current_reloc_data_pos], &reloc, sizeof(reloc));
- current_reloc_data_pos += sizeof(reloc);
-
- //Enumerate relocations in table
- for(relocation_table::relocation_list::const_iterator r = reloc_list.begin(); r != reloc_list.end(); ++r)
- {
- //Save relocations
- uint16_t reloc_value = (*r).get_item();
- memcpy(&raw_data[current_reloc_data_pos], &reloc_value, sizeof(reloc_value));
- current_reloc_data_pos += sizeof(reloc_value);
- }
-
- if(current_reloc_data_pos % sizeof(uint32_t)) //If end of table is not DWORD-aligned
- {
- memset(&raw_data[current_reloc_data_pos], 0, sizeof(uint16_t)); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation
- current_reloc_data_pos += sizeof(uint16_t);
- }
- }
-
- image_directory ret(pe.rva_from_section_offset(reloc_section, start_reloc_pos), needed_size - size_delta);
-
- //Adjust section raw and virtual sizes
- pe.recalculate_section_sizes(reloc_section, auto_strip_last_section);
-
- //If auto-rewrite of PE headers is required
- if(save_to_pe_header)
- {
- pe.set_directory_rva(image_directory_entry_basereloc, ret.get_rva());
- pe.set_directory_size(image_directory_entry_basereloc, ret.get_size());
-
- pe.clear_characteristics_flags(image_file_relocs_stripped);
- pe.set_dll_characteristics(pe.get_dll_characteristics() | image_dllcharacteristics_dynamic_base);
- }
-
- return ret;
-}
-
-//Recalculates image base with the help of relocation tables
-void rebase_image(pe_base& pe, const relocation_table_list& tables, uint64_t new_base)
-{
- pe.get_pe_type() == pe_type_32
- ? rebase_image_base<pe_types_class_32>(pe, tables, new_base)
- : rebase_image_base<pe_types_class_64>(pe, tables, new_base);
-}
-
-//RELOCATIONS
-//Recalculates image base with the help of relocation tables
-//Recalculates VAs of DWORDS/QWORDS in image according to relocations
-//Notice: if you move some critical structures like TLS, image relocations will not fix new
-//positions of TLS VAs. Instead, some bytes that now doesn't belong to TLS will be fixed.
-//It is recommended to rebase image in the very beginning and move all structures afterwards.
-template<typename PEClassType>
-void rebase_image_base(pe_base& pe, const relocation_table_list& tables, uint64_t new_base)
-{
- //Get current image base value
- typename PEClassType::BaseSize image_base;
- pe.get_image_base(image_base);
-
- //ImageBase difference
- typename PEClassType::BaseSize base_rel = static_cast<typename PEClassType::BaseSize>(static_cast<int64_t>(new_base) - image_base);
-
- //We need to fix addresses from relocation tables
- //Enumerate relocation tables
- for(relocation_table_list::const_iterator it = tables.begin(); it != tables.end(); ++it)
- {
- const relocation_table::relocation_list& relocs = (*it).get_relocations();
-
- uint32_t base_rva = (*it).get_rva();
-
- //Enumerate relocations
- for(relocation_table::relocation_list::const_iterator rel = relocs.begin(); rel != relocs.end(); ++rel)
- {
- //Skip ABSOLUTE entries
- if((*rel).get_type() == pe_win::image_rel_based_absolute)
- continue;
-
- //Recalculate value by RVA and rewrite it
- uint32_t current_rva = base_rva + (*rel).get_rva();
- typename PEClassType::BaseSize value = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_rva, section_data_raw, true);
- value += base_rel;
- memcpy(pe.section_data_from_rva(current_rva, true), &value, sizeof(value));
- }
- }
-
- //Finally, save new image base
- pe.set_image_base_64(new_base);
-}
-}
diff --git a/tools/pe_bliss/pe_relocations.h b/tools/pe_bliss/pe_relocations.h
deleted file mode 100644
index 1bc8b2a405..0000000000
--- a/tools/pe_bliss/pe_relocations.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include "pe_structures.h"
-#include "pe_base.h"
-#include "pe_directory.h"
-
-namespace pe_bliss
-{
-//Class representing relocation entry
-//RVA of relocation is not actually RVA, but
-//(real RVA) - (RVA of table)
-class relocation_entry
-{
-public:
- //Default constructor
- relocation_entry();
- //Constructor from relocation item (WORD)
- explicit relocation_entry(uint16_t relocation_value);
- //Constructor from relative rva and relocation type
- relocation_entry(uint16_t rrva, uint16_t type);
-
- //Returns RVA of relocation (actually, relative RVA from relocation table RVA)
- uint16_t get_rva() const;
- //Returns type of relocation
- uint16_t get_type() const;
-
- //Returns relocation item (rrva + type)
- uint16_t get_item() const;
-
-public: //Setters do not change everything inside image, they are used by PE class
- //You can also use them to rebuild relocations using rebuild_relocations()
-
- //Sets RVA of relocation (actually, relative RVA from relocation table RVA)
- void set_rva(uint16_t rva);
- //Sets type of relocation
- void set_type(uint16_t type);
-
- //Sets relocation item (rrva + type)
- void set_item(uint16_t item);
-
-private:
- uint16_t rva_;
- uint16_t type_;
-};
-
-//Class representing relocation table
-class relocation_table
-{
-public:
- typedef std::vector<relocation_entry> relocation_list;
-
-public:
- //Default constructor
- relocation_table();
- //Constructor from RVA of relocation table
- explicit relocation_table(uint32_t rva);
-
- //Returns relocation list
- const relocation_list& get_relocations() const;
- //Returns RVA of block
- uint32_t get_rva() const;
-
-public: //These functions do not change everything inside image, they are used by PE class
- //You can also use them to rebuild relocations using rebuild_relocations()
-
- //Adds relocation to table
- void add_relocation(const relocation_entry& entry);
- //Returns changeable relocation list
- relocation_list& get_relocations();
- //Sets RVA of block
- void set_rva(uint32_t rva);
-
-private:
- uint32_t rva_;
- relocation_list relocations_;
-};
-
-typedef std::vector<relocation_table> relocation_table_list;
-
-//Get relocation list of pe file, supports one-word sized relocations only
-//If list_absolute_entries = true, IMAGE_REL_BASED_ABSOLUTE will be listed
-const relocation_table_list get_relocations(const pe_base& pe, bool list_absolute_entries = false);
-
-//Simple relocations rebuilder
-//To keep PE file working, don't remove any of existing relocations in
-//relocation_table_list returned by a call to get_relocations() function
-//auto_strip_last_section - if true and relocations are placed in the last section, it will be automatically stripped
-//offset_from_section_start - offset from the beginning of reloc_section, where relocations data will be situated
-//If save_to_pe_header is true, PE header will be modified automatically
-const image_directory rebuild_relocations(pe_base& pe, const relocation_table_list& relocs, section& reloc_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-
-//Recalculates image base with the help of relocation tables
-//Recalculates VAs of DWORDS/QWORDS in image according to relocations
-//Notice: if you move some critical structures like TLS, image relocations will not fix new
-//positions of TLS VAs. Instead, some bytes that now doesn't belong to TLS will be fixed.
-//It is recommended to rebase image in the very beginning and move all structures afterwards.
-void rebase_image(pe_base& pe, const relocation_table_list& tables, uint64_t new_base);
-
-template<typename PEClassType>
-void rebase_image_base(pe_base& pe, const relocation_table_list& tables, uint64_t new_base);
-}
diff --git a/tools/pe_bliss/pe_resource_manager.cpp b/tools/pe_bliss/pe_resource_manager.cpp
deleted file mode 100644
index 0ee7840ff0..0000000000
--- a/tools/pe_bliss/pe_resource_manager.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <algorithm>
-#include <sstream>
-#include <iomanip>
-#include <math.h>
-#include <string.h>
-#include "pe_resource_manager.h"
-#include "resource_internal.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Constructor from root resource directory
-pe_resource_manager::pe_resource_manager(resource_directory& root_directory)
- :pe_resource_viewer(root_directory), root_dir_edit_(root_directory)
-{}
-
-resource_directory& pe_resource_manager::get_root_directory()
-{
- return root_dir_edit_;
-}
-
-//Removes all resources of given type or root name
-//If there's more than one directory entry of a given type, only the
-//first one will be deleted (that's an unusual situation)
-//Returns true if resource was deleted
-bool pe_resource_manager::remove_resource_type(resource_type type)
-{
- //Search for resource type
- resource_directory::entry_list& entries = root_dir_edit_.get_entry_list();
- resource_directory::entry_list::iterator it = std::find_if(entries.begin(), entries.end(), resource_directory::id_entry_finder(type));
- if(it != entries.end())
- {
- //Remove it, if found
- entries.erase(it);
- return true;
- }
-
- return false;
-}
-
-bool pe_resource_manager::remove_resource(const std::wstring& root_name)
-{
- //Search for resource type
- resource_directory::entry_list& entries = root_dir_edit_.get_entry_list();
- resource_directory::entry_list::iterator it = std::find_if(entries.begin(), entries.end(), resource_directory::name_entry_finder(root_name));
- if(it != entries.end())
- {
- //Remove it, if found
- entries.erase(it);
- return true;
- }
-
- return false;
-}
-
-//Helper to remove resource
-bool pe_resource_manager::remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder)
-{
- //Search for resource type
- resource_directory::entry_list& entries_type = root_dir_edit_.get_entry_list();
- resource_directory::entry_list::iterator it_type = std::find_if(entries_type.begin(), entries_type.end(), root_finder);
- if(it_type != entries_type.end())
- {
- //Search for resource name/ID with "finder"
- resource_directory::entry_list& entries_name = (*it_type).get_resource_directory().get_entry_list();
- resource_directory::entry_list::iterator it_name = std::find_if(entries_name.begin(), entries_name.end(), finder);
- if(it_name != entries_name.end())
- {
- //Erase resource, if found
- entries_name.erase(it_name);
- if(entries_name.empty())
- entries_type.erase(it_type);
-
- return true;
- }
- }
-
- return false;
-}
-
-//Removes all resource languages by resource type/root name and name
-//Deletes only one entry of given type and name
-//Returns true if resource was deleted
-bool pe_resource_manager::remove_resource(resource_type type, const std::wstring& name)
-{
- return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(name));
-}
-
-bool pe_resource_manager::remove_resource(const std::wstring& root_name, const std::wstring& name)
-{
- return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(name));
-}
-
-//Removes all resource languages by resource type/root name and ID
-//Deletes only one entry of given type and ID
-//Returns true if resource was deleted
-bool pe_resource_manager::remove_resource(resource_type type, uint32_t id)
-{
- return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(id));
-}
-
-bool pe_resource_manager::remove_resource(const std::wstring& root_name, uint32_t id)
-{
- return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(id));
-}
-
-//Helper to remove resource
-bool pe_resource_manager::remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder, uint32_t language)
-{
- //Search for resource type
- resource_directory::entry_list& entries_type = root_dir_edit_.get_entry_list();
- resource_directory::entry_list::iterator it_type = std::find_if(entries_type.begin(), entries_type.end(), root_finder);
- if(it_type != entries_type.end())
- {
- //Search for resource name/ID with "finder"
- resource_directory::entry_list& entries_name = (*it_type).get_resource_directory().get_entry_list();
- resource_directory::entry_list::iterator it_name = std::find_if(entries_name.begin(), entries_name.end(), finder);
- if(it_name != entries_name.end())
- {
- //Search for resource language
- resource_directory::entry_list& entries_lang = (*it_name).get_resource_directory().get_entry_list();
- resource_directory::entry_list::iterator it_lang = std::find_if(entries_lang.begin(), entries_lang.end(), resource_directory::id_entry_finder(language));
- if(it_lang != entries_lang.end())
- {
- //Erase resource, if found
- entries_lang.erase(it_lang);
- if(entries_lang.empty())
- {
- entries_name.erase(it_name);
- if(entries_name.empty())
- entries_type.erase(it_type);
- }
-
- return true;
- }
- }
- }
-
- return false;
-}
-
-//Removes resource language by resource type/root name and name
-//Deletes only one entry of given type, name and language
-//Returns true if resource was deleted
-bool pe_resource_manager::remove_resource(resource_type type, const std::wstring& name, uint32_t language)
-{
- return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(name), language);
-}
-
-bool pe_resource_manager::remove_resource(const std::wstring& root_name, const std::wstring& name, uint32_t language)
-{
- return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(name), language);
-}
-
-//Removes recource language by resource type/root name and ID
-//Deletes only one entry of given type, ID and language
-//Returns true if resource was deleted
-bool pe_resource_manager::remove_resource(resource_type type, uint32_t id, uint32_t language)
-{
- return remove_resource(resource_directory::entry_finder(type), resource_directory::entry_finder(id), language);
-}
-
-bool pe_resource_manager::remove_resource(const std::wstring& root_name, uint32_t id, uint32_t language)
-{
- return remove_resource(resource_directory::entry_finder(root_name), resource_directory::entry_finder(id), language);
-}
-
-//Helper to add/replace resource
-void pe_resource_manager::add_resource(const std::string& data, resource_type type, resource_directory_entry& new_entry, const resource_directory::entry_finder& finder, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_type_entry;
- new_type_entry.set_id(type);
-
- add_resource(data, new_type_entry, resource_directory::entry_finder(type), new_entry, finder, language, codepage, timestamp);
-}
-
-//Helper to add/replace resource
-void pe_resource_manager::add_resource(const std::string& data, const std::wstring& root_name, resource_directory_entry& new_entry, const resource_directory::entry_finder& finder, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_type_entry;
- new_type_entry.set_name(root_name);
-
- add_resource(data, new_type_entry, resource_directory::entry_finder(root_name), new_entry, finder, language, codepage, timestamp);
-}
-
-//Helper to add/replace resource
-void pe_resource_manager::add_resource(const std::string& data, resource_directory_entry& new_root_entry, const resource_directory::entry_finder& root_finder, resource_directory_entry& new_entry, const resource_directory::entry_finder& finder, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- //Search for resource type
- resource_directory::entry_list* entries = &root_dir_edit_.get_entry_list();
- resource_directory::entry_list::iterator it = std::find_if(entries->begin(), entries->end(), root_finder);
- if(it == entries->end())
- {
- //Add resource type directory, if it was not found
- resource_directory dir;
- dir.set_timestamp(timestamp);
- new_root_entry.add_resource_directory(dir);
- entries->push_back(new_root_entry);
- it = entries->end() - 1;
- }
-
- //Search for resource name/ID directory with "finder"
- entries = &(*it).get_resource_directory().get_entry_list();
- it = std::find_if(entries->begin(), entries->end(), finder);
- if(it == entries->end())
- {
- //Add resource name/ID directory, if it was not found
- resource_directory dir;
- dir.set_timestamp(timestamp);
- new_entry.add_resource_directory(dir);
- entries->push_back(new_entry);
- it = entries->end() - 1;
- }
-
- //Search for data resource entry by language
- entries = &(*it).get_resource_directory().get_entry_list();
- it = std::find_if(entries->begin(), entries->end(), resource_directory::id_entry_finder(language));
- if(it != entries->end())
- entries->erase(it); //Erase it, if found
-
- //Add new data entry
- resource_directory_entry new_dir_data_entry;
- resource_data_entry data_dir(data, codepage);
- new_dir_data_entry.add_data_entry(data_dir);
- new_dir_data_entry.set_id(language);
- entries->push_back(new_dir_data_entry);
-}
-
-//Adds resource. If resource already exists, replaces it
-void pe_resource_manager::add_resource(const std::string& data, resource_type type, const std::wstring& name, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_entry;
- new_entry.set_name(name);
-
- add_resource(data, type, new_entry, resource_directory::entry_finder(name), language, codepage, timestamp);
-}
-
-//Adds resource. If resource already exists, replaces it
-void pe_resource_manager::add_resource(const std::string& data, const std::wstring& root_name, const std::wstring& name, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_entry;
- new_entry.set_name(name);
-
- add_resource(data, root_name, new_entry, resource_directory::entry_finder(name), language, codepage, timestamp);
-}
-
-//Adds resource. If resource already exists, replaces it
-void pe_resource_manager::add_resource(const std::string& data, resource_type type, uint32_t id, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_entry;
- new_entry.set_id(id);
-
- add_resource(data, type, new_entry, resource_directory::entry_finder(id), language, codepage, timestamp);
-}
-
-//Adds resource. If resource already exists, replaces it
-void pe_resource_manager::add_resource(const std::string& data, const std::wstring& root_name, uint32_t id, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_entry;
- new_entry.set_id(id);
-
- add_resource(data, root_name, new_entry, resource_directory::entry_finder(id), language, codepage, timestamp);
-}
-}
diff --git a/tools/pe_bliss/pe_resource_manager.h b/tools/pe_bliss/pe_resource_manager.h
deleted file mode 100644
index 85d7f44a8a..0000000000
--- a/tools/pe_bliss/pe_resource_manager.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <map>
-#include <sstream>
-#include <string>
-#include <memory>
-#include "pe_base.h"
-#include "pe_structures.h"
-#include "pe_resources.h"
-#include "message_table.h"
-#include "file_version_info.h"
-#include "pe_resource_viewer.h"
-#include "resource_data_info.h"
-
-namespace pe_bliss
-{
-//Derived class to edit PE resources
-class pe_resource_manager : public pe_resource_viewer
-{
-public:
- //Constructor from root resource directory
- explicit pe_resource_manager(resource_directory& root_directory);
-
- resource_directory& get_root_directory();
-
-public: //Resource editing
- //Removes all resources of given type or root name
- //If there's more than one directory entry of a given type, only the
- //first one will be deleted (that's an unusual situation)
- //Returns true if resource was deleted
- bool remove_resource_type(resource_type type);
- bool remove_resource(const std::wstring& root_name);
-
- //Removes all resource languages by resource type/root name and name
- //Deletes only one entry of given type and name
- //Returns true if resource was deleted
- bool remove_resource(resource_type type, const std::wstring& name);
- bool remove_resource(const std::wstring& root_name, const std::wstring& name);
- //Removes all resource languages by resource type/root name and ID
- //Deletes only one entry of given type and ID
- //Returns true if resource was deleted
- bool remove_resource(resource_type type, uint32_t id);
- bool remove_resource(const std::wstring& root_name, uint32_t id);
-
- //Removes resource language by resource type/root name and name
- //Deletes only one entry of given type, name and language
- //Returns true if resource was deleted
- bool remove_resource(resource_type type, const std::wstring& name, uint32_t language);
- bool remove_resource(const std::wstring& root_name, const std::wstring& name, uint32_t language);
- //Removes recource language by resource type/root name and ID
- //Deletes only one entry of given type, ID and language
- //Returns true if resource was deleted
- bool remove_resource(resource_type type, uint32_t id, uint32_t language);
- bool remove_resource(const std::wstring& root_name, uint32_t id, uint32_t language);
-
- //Adds resource. If resource already exists, replaces it
- //timestamp will be used for directories that will be added
- void add_resource(const std::string& data, resource_type type, const std::wstring& name, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0);
- void add_resource(const std::string& data, const std::wstring& root_name, const std::wstring& name, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0);
- //Adds resource. If resource already exists, replaces it
- //timestamp will be used for directories that will be added
- void add_resource(const std::string& data, resource_type type, uint32_t id, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0);
- void add_resource(const std::string& data, const std::wstring& root_name, uint32_t id, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0);
-
-public:
- //Helpers to add/replace resource
- void add_resource(const std::string& data, resource_type type,
- resource_directory_entry& new_entry,
- const resource_directory::entry_finder& finder,
- uint32_t language, uint32_t codepage, uint32_t timestamp);
-
- void add_resource(const std::string& data, const std::wstring& root_name,
- resource_directory_entry& new_entry,
- const resource_directory::entry_finder& finder,
- uint32_t language, uint32_t codepage, uint32_t timestamp);
-
- void add_resource(const std::string& data, resource_directory_entry& new_root_entry,
- const resource_directory::entry_finder& root_finder,
- resource_directory_entry& new_entry,
- const resource_directory::entry_finder& finder,
- uint32_t language, uint32_t codepage, uint32_t timestamp);
-
-private:
- //Root resource directory. We're not copying it, because it might be heavy
- resource_directory& root_dir_edit_;
-
- //Helper to remove resource
- bool remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder);
-
- //Helper to remove resource
- bool remove_resource(const resource_directory::entry_finder& root_finder, const resource_directory::entry_finder& finder, uint32_t language);
-};
-}
diff --git a/tools/pe_bliss/pe_resource_viewer.cpp b/tools/pe_bliss/pe_resource_viewer.cpp
deleted file mode 100644
index 712cc28d9b..0000000000
--- a/tools/pe_bliss/pe_resource_viewer.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <algorithm>
-#include <cmath>
-#include "pe_resource_viewer.h"
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Constructor from root resource_directory
-pe_resource_viewer::pe_resource_viewer(const resource_directory& root_directory)
- :root_dir_(root_directory)
-{}
-
-const resource_directory& pe_resource_viewer::get_root_directory() const
-{
- return root_dir_;
-}
-
-//Finder helpers
-bool pe_resource_viewer::has_name::operator()(const resource_directory_entry& entry) const
-{
- return entry.is_named();
-}
-
-bool pe_resource_viewer::has_id::operator()(const resource_directory_entry& entry) const
-{
- return !entry.is_named();
-}
-
-//Lists resource types existing in PE file (non-named only)
-const pe_resource_viewer::resource_type_list pe_resource_viewer::list_resource_types() const
-{
- resource_type_list ret;
-
- //Get root directory entries list
- const resource_directory::entry_list& entries = root_dir_.get_entry_list();
- for(resource_directory::entry_list::const_iterator it = entries.begin(); it != entries.end(); ++it)
- {
- //List all non-named items
- if(!(*it).is_named())
- ret.push_back((*it).get_id());
- }
-
- return ret;
-}
-
-//Returns true if resource type exists
-bool pe_resource_viewer::resource_exists(resource_type type) const
-{
- const resource_directory::entry_list& entries = root_dir_.get_entry_list();
- return std::find_if(entries.begin(), entries.end(), resource_directory::id_entry_finder(type)) != entries.end();
-}
-
-//Returns true if resource name exists
-bool pe_resource_viewer::resource_exists(const std::wstring& root_name) const
-{
- const resource_directory::entry_list& entries = root_dir_.get_entry_list();
- return std::find_if(entries.begin(), entries.end(), resource_directory::name_entry_finder(root_name)) != entries.end();
-}
-
-//Helper function to get name list from entry list
-const pe_resource_viewer::resource_name_list pe_resource_viewer::get_name_list(const resource_directory::entry_list& entries)
-{
- resource_name_list ret;
-
- for(resource_directory::entry_list::const_iterator it = entries.begin(); it != entries.end(); ++it)
- {
- //List all named items
- if((*it).is_named())
- ret.push_back((*it).get_name());
- }
-
- return ret;
-}
-
-//Helper function to get ID list from entry list
-const pe_resource_viewer::resource_id_list pe_resource_viewer::get_id_list(const resource_directory::entry_list& entries)
-{
- resource_id_list ret;
-
- for(resource_directory::entry_list::const_iterator it = entries.begin(); it != entries.end(); ++it)
- {
- //List all non-named items
- if(!(*it).is_named())
- ret.push_back((*it).get_id());
- }
-
- return ret;
-}
-
-//Lists resource names existing in PE file by resource type
-const pe_resource_viewer::resource_name_list pe_resource_viewer::list_resource_names(resource_type type) const
-{
- return get_name_list(root_dir_.entry_by_id(type).get_resource_directory().get_entry_list());
-}
-
-//Lists resource names existing in PE file by resource name
-const pe_resource_viewer::resource_name_list pe_resource_viewer::list_resource_names(const std::wstring& root_name) const
-{
- return get_name_list(root_dir_.entry_by_name(root_name).get_resource_directory().get_entry_list());
-}
-
-//Lists resource IDs existing in PE file by resource type
-const pe_resource_viewer::resource_id_list pe_resource_viewer::list_resource_ids(resource_type type) const
-{
- return get_id_list(root_dir_.entry_by_id(type).get_resource_directory().get_entry_list());
-}
-
-//Lists resource IDs existing in PE file by resource name
-const pe_resource_viewer::resource_id_list pe_resource_viewer::list_resource_ids(const std::wstring& root_name) const
-{
- return get_id_list(root_dir_.entry_by_name(root_name).get_resource_directory().get_entry_list());
-}
-
-//Returns resource count by type
-unsigned long pe_resource_viewer::get_resource_count(resource_type type) const
-{
- return static_cast<unsigned long>(
- root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .get_entry_list()
- .size());
-}
-
-//Returns resource count by name
-unsigned long pe_resource_viewer::get_resource_count(const std::wstring& root_name) const
-{
- return static_cast<unsigned long>(
- root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .get_entry_list()
- .size());
-}
-
-//Returns language count of resource by resource type and name
-unsigned long pe_resource_viewer::get_language_count(resource_type type, const std::wstring& name) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id()));
-}
-
-//Returns language count of resource by resource names
-unsigned long pe_resource_viewer::get_language_count(const std::wstring& root_name, const std::wstring& name) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id()));
-}
-
-//Returns language count of resource by resource type and ID
-unsigned long pe_resource_viewer::get_language_count(resource_type type, uint32_t id) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id()));
-}
-
-//Returns language count of resource by resource name and ID
-unsigned long pe_resource_viewer::get_language_count(const std::wstring& root_name, uint32_t id) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return static_cast<unsigned long>(std::count_if(entries.begin(), entries.end(), has_id()));
-}
-
-//Lists resource languages by resource type and name
-const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(resource_type type, const std::wstring& name) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return get_id_list(entries);
-}
-
-//Lists resource languages by resource names
-const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(const std::wstring& root_name, const std::wstring& name) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return get_id_list(entries);
-}
-
-//Lists resource languages by resource type and ID
-const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(resource_type type, uint32_t id) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return get_id_list(entries);
-}
-
-//Lists resource languages by resource name and ID
-const pe_resource_viewer::resource_language_list pe_resource_viewer::list_resource_languages(const std::wstring& root_name, uint32_t id) const
-{
- const resource_directory::entry_list& entries =
- root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- return get_id_list(entries);
-}
-
-//Returns raw resource data by type, name and language
-const resource_data_info pe_resource_viewer::get_resource_data_by_name(uint32_t language, resource_type type, const std::wstring& name) const
-{
- return resource_data_info(root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .entry_by_id(language)
- .get_data_entry()); //Data directory
-}
-
-//Returns raw resource data by root name, name and language
-const resource_data_info pe_resource_viewer::get_resource_data_by_name(uint32_t language, const std::wstring& root_name, const std::wstring& name) const
-{
- return resource_data_info(root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .entry_by_id(language)
- .get_data_entry()); //Data directory
-}
-
-//Returns raw resource data by type, ID and language
-const resource_data_info pe_resource_viewer::get_resource_data_by_id(uint32_t language, resource_type type, uint32_t id) const
-{
- return resource_data_info(root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .entry_by_id(language)
- .get_data_entry()); //Data directory
-}
-
-//Returns raw resource data by root name, ID and language
-const resource_data_info pe_resource_viewer::get_resource_data_by_id(uint32_t language, const std::wstring& root_name, uint32_t id) const
-{
- return resource_data_info(root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .entry_by_id(language)
- .get_data_entry()); //Data directory
-}
-
-//Returns raw resource data by type, name and index in language directory (instead of language)
-const resource_data_info pe_resource_viewer::get_resource_data_by_name(resource_type type, const std::wstring& name, uint32_t index) const
-{
- const resource_directory::entry_list& entries = root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- if(entries.size() <= index)
- throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found);
-
- return resource_data_info(entries.at(index).get_data_entry()); //Data directory
-}
-
-//Returns raw resource data by root name, name and index in language directory (instead of language)
-const resource_data_info pe_resource_viewer::get_resource_data_by_name(const std::wstring& root_name, const std::wstring& name, uint32_t index) const
-{
- const resource_directory::entry_list& entries = root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_name(name)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- if(entries.size() <= index)
- throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found);
-
- return resource_data_info(entries.at(index).get_data_entry()); //Data directory
-}
-
-//Returns raw resource data by type, ID and index in language directory (instead of language)
-const resource_data_info pe_resource_viewer::get_resource_data_by_id(resource_type type, uint32_t id, uint32_t index) const
-{
- const resource_directory::entry_list& entries = root_dir_ //Type directory
- .entry_by_id(type)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- if(entries.size() <= index)
- throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found);
-
- return resource_data_info(entries.at(index).get_data_entry()); //Data directory
-}
-
-//Returns raw resource data by root name, ID and index in language directory (instead of language)
-const resource_data_info pe_resource_viewer::get_resource_data_by_id(const std::wstring& root_name, uint32_t id, uint32_t index) const
-{
- const resource_directory::entry_list& entries = root_dir_ //Type directory
- .entry_by_name(root_name)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(id)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- if(entries.size() <= index)
- throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found);
-
- return resource_data_info(entries.at(index).get_data_entry()); //Data directory
-}
-}
diff --git a/tools/pe_bliss/pe_resource_viewer.h b/tools/pe_bliss/pe_resource_viewer.h
deleted file mode 100644
index e585da6a87..0000000000
--- a/tools/pe_bliss/pe_resource_viewer.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <map>
-#include <string>
-#include "pe_structures.h"
-#include "pe_resources.h"
-#include "message_table.h"
-#include "resource_data_info.h"
-
-namespace pe_bliss
-{
- //PE resource manager allows to read resources from PE files
-class pe_resource_viewer
-{
-public:
- //Resource type enumeration
- enum resource_type
- {
- resource_cursor = 1,
- resource_bitmap = 2,
- resource_icon = 3,
- resource_menu = 4,
- resource_dialog = 5,
- resource_string = 6,
- resource_fontdir = 7,
- resource_font = 8,
- resource_accelerator = 9,
- resource_rcdata = 10,
- resource_message_table = 11,
- resource_cursor_group = 12,
- resource_icon_group = 14,
- resource_version = 16,
- resource_dlginclude = 17,
- resource_plugplay = 19,
- resource_vxd = 20,
- resource_anicursor = 21,
- resource_aniicon = 22,
- resource_html = 23,
- resource_manifest = 24
- };
-
-public:
- //Some useful typedefs
- typedef std::vector<uint32_t> resource_type_list;
- typedef std::vector<uint32_t> resource_id_list;
- typedef std::vector<std::wstring> resource_name_list;
- typedef std::vector<uint32_t> resource_language_list;
-
-public:
- //Constructor from root resource_directory from PE file
- explicit pe_resource_viewer(const resource_directory& root_directory);
-
- const resource_directory& get_root_directory() const;
-
- //Lists resource types existing in PE file (non-named only)
- const resource_type_list list_resource_types() const;
- //Returns true if resource type exists
- bool resource_exists(resource_type type) const;
- //Returns true if resource name exists
- bool resource_exists(const std::wstring& root_name) const;
-
- //Lists resource names existing in PE file by resource type
- const resource_name_list list_resource_names(resource_type type) const;
- //Lists resource names existing in PE file by resource name
- const resource_name_list list_resource_names(const std::wstring& root_name) const;
- //Lists resource IDs existing in PE file by resource type
- const resource_id_list list_resource_ids(resource_type type) const;
- //Lists resource IDs existing in PE file by resource name
- const resource_id_list list_resource_ids(const std::wstring& root_name) const;
- //Returns resource count by type
- unsigned long get_resource_count(resource_type type) const;
- //Returns resource count by name
- unsigned long get_resource_count(const std::wstring& root_name) const;
-
- //Returns language count of resource by resource type and name
- unsigned long get_language_count(resource_type type, const std::wstring& name) const;
- //Returns language count of resource by resource names
- unsigned long get_language_count(const std::wstring& root_name, const std::wstring& name) const;
- //Returns language count of resource by resource type and ID
- unsigned long get_language_count(resource_type type, uint32_t id) const;
- //Returns language count of resource by resource name and ID
- unsigned long get_language_count(const std::wstring& root_name, uint32_t id) const;
- //Lists resource languages by resource type and name
- const resource_language_list list_resource_languages(resource_type type, const std::wstring& name) const;
- //Lists resource languages by resource names
- const resource_language_list list_resource_languages(const std::wstring& root_name, const std::wstring& name) const;
- //Lists resource languages by resource type and ID
- const resource_language_list list_resource_languages(resource_type type, uint32_t id) const;
- //Lists resource languages by resource name and ID
- const resource_language_list list_resource_languages(const std::wstring& root_name, uint32_t id) const;
-
- //Returns raw resource data by type, name and language
- const resource_data_info get_resource_data_by_name(uint32_t language, resource_type type, const std::wstring& name) const;
- //Returns raw resource data by root name, name and language
- const resource_data_info get_resource_data_by_name(uint32_t language, const std::wstring& root_name, const std::wstring& name) const;
- //Returns raw resource data by type, ID and language
- const resource_data_info get_resource_data_by_id(uint32_t language, resource_type type, uint32_t id) const;
- //Returns raw resource data by root name, ID and language
- const resource_data_info get_resource_data_by_id(uint32_t language, const std::wstring& root_name, uint32_t id) const;
- //Returns raw resource data by type, name and index in language directory (instead of language)
- const resource_data_info get_resource_data_by_name(resource_type type, const std::wstring& name, uint32_t index = 0) const;
- //Returns raw resource data by root name, name and index in language directory (instead of language)
- const resource_data_info get_resource_data_by_name(const std::wstring& root_name, const std::wstring& name, uint32_t index = 0) const;
- //Returns raw resource data by type, ID and index in language directory (instead of language)
- const resource_data_info get_resource_data_by_id(resource_type type, uint32_t id, uint32_t index = 0) const;
- //Returns raw resource data by root name, ID and index in language directory (instead of language)
- const resource_data_info get_resource_data_by_id(const std::wstring& root_name, uint32_t id, uint32_t index = 0) const;
-
-protected:
- //Root resource directory. We're not copying it, because it might be heavy
- const resource_directory& root_dir_;
-
- //Helper function to get ID list from entry list
- static const resource_id_list get_id_list(const resource_directory::entry_list& entries);
- //Helper function to get name list from entry list
- static const resource_name_list get_name_list(const resource_directory::entry_list& entries);
-
-protected:
- //Helper structure - finder of resource_directory_entry that is named
- struct has_name
- {
- public:
- bool operator()(const resource_directory_entry& entry) const;
- };
-
- //Helper structure - finder of resource_directory_entry that is not named (has id)
- struct has_id
- {
- public:
- bool operator()(const resource_directory_entry& entry) const;
- };
-};
-}
diff --git a/tools/pe_bliss/pe_resources.cpp b/tools/pe_bliss/pe_resources.cpp
deleted file mode 100644
index 189aba1f76..0000000000
--- a/tools/pe_bliss/pe_resources.cpp
+++ /dev/null
@@ -1,726 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <algorithm>
-#include <string.h>
-#include "pe_resources.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//RESOURCES
-//Default constructor
-resource_data_entry::resource_data_entry()
- :codepage_(0)
-{}
-
-//Constructor from data
-resource_data_entry::resource_data_entry(const std::string& data, uint32_t codepage)
- :codepage_(codepage), data_(data)
-{}
-
-//Returns resource data codepage
-uint32_t resource_data_entry::get_codepage() const
-{
- return codepage_;
-}
-
-//Returns resource data
-const std::string& resource_data_entry::get_data() const
-{
- return data_;
-}
-
-//Sets resource data codepage
-void resource_data_entry::set_codepage(uint32_t codepage)
-{
- codepage_ = codepage;
-}
-
-//Sets resource data
-void resource_data_entry::set_data(const std::string& data)
-{
- data_ = data;
-}
-
-//Default constructor
-resource_directory_entry::includes::includes()
- :data_(0)
-{}
-
-//Default constructor
-resource_directory_entry::resource_directory_entry()
- :id_(0), includes_data_(false), named_(false)
-{}
-
-//Copy constructor
-resource_directory_entry::resource_directory_entry(const resource_directory_entry& other)
- :id_(other.id_), name_(other.name_), includes_data_(other.includes_data_), named_(other.named_)
-{
- //If union'ed pointer is not zero
- if(other.ptr_.data_)
- {
- if(other.includes_data())
- ptr_.data_ = new resource_data_entry(*other.ptr_.data_);
- else
- ptr_.dir_ = new resource_directory(*other.ptr_.dir_);
- }
-}
-
-//Copy assignment operator
-resource_directory_entry& resource_directory_entry::operator=(const resource_directory_entry& other)
-{
- release();
-
- id_ = other.id_;
- name_ = other.name_;
- includes_data_ = other.includes_data_;
- named_ = other.named_;
-
- //If other union'ed pointer is not zero
- if(other.ptr_.data_)
- {
- if(other.includes_data())
- ptr_.data_ = new resource_data_entry(*other.ptr_.data_);
- else
- ptr_.dir_ = new resource_directory(*other.ptr_.dir_);
- }
-
- return *this;
-}
-
-//Destroys included data
-void resource_directory_entry::release()
-{
- //If union'ed pointer is not zero
- if(ptr_.data_)
- {
- if(includes_data())
- delete ptr_.data_;
- else
- delete ptr_.dir_;
-
- ptr_.data_ = 0;
- }
-}
-
-//Destructor
-resource_directory_entry::~resource_directory_entry()
-{
- release();
-}
-
-//Returns entry ID
-uint32_t resource_directory_entry::get_id() const
-{
- return id_;
-}
-
-//Returns entry name
-const std::wstring& resource_directory_entry::get_name() const
-{
- return name_;
-}
-
-//Returns true, if entry has name
-//Returns false, if entry has ID
-bool resource_directory_entry::is_named() const
-{
- return named_;
-}
-
-//Returns true, if entry includes resource_data_entry
-//Returns false, if entry includes resource_directory
-bool resource_directory_entry::includes_data() const
-{
- return includes_data_;
-}
-
-//Returns resource_directory if entry includes it, otherwise throws an exception
-const resource_directory& resource_directory_entry::get_resource_directory() const
-{
- if(!ptr_.dir_ || includes_data_)
- throw pe_exception("Resource directory entry does not contain resource directory", pe_exception::resource_directory_entry_error);
-
- return *ptr_.dir_;
-}
-
-//Returns resource_data_entry if entry includes it, otherwise throws an exception
-const resource_data_entry& resource_directory_entry::get_data_entry() const
-{
- if(!ptr_.data_ || !includes_data_)
- throw pe_exception("Resource directory entry does not contain resource data entry", pe_exception::resource_directory_entry_error);
-
- return *ptr_.data_;
-}
-
-//Returns resource_directory if entry includes it, otherwise throws an exception
-resource_directory& resource_directory_entry::get_resource_directory()
-{
- if(!ptr_.dir_ || includes_data_)
- throw pe_exception("Resource directory entry does not contain resource directory", pe_exception::resource_directory_entry_error);
-
- return *ptr_.dir_;
-}
-
-//Returns resource_data_entry if entry includes it, otherwise throws an exception
-resource_data_entry& resource_directory_entry::get_data_entry()
-{
- if(!ptr_.data_ || !includes_data_)
- throw pe_exception("Resource directory entry does not contain resource data entry", pe_exception::resource_directory_entry_error);
-
- return *ptr_.data_;
-}
-
-//Sets entry name
-void resource_directory_entry::set_name(const std::wstring& name)
-{
- name_ = name;
- named_ = true;
- id_ = 0;
-}
-
-//Sets entry ID
-void resource_directory_entry::set_id(uint32_t id)
-{
- id_ = id;
- named_ = false;
- name_.clear();
-}
-
-//Adds resource_data_entry
-void resource_directory_entry::add_data_entry(const resource_data_entry& entry)
-{
- release();
- ptr_.data_ = new resource_data_entry(entry);
- includes_data_ = true;
-}
-
-//Adds resource_directory
-void resource_directory_entry::add_resource_directory(const resource_directory& dir)
-{
- release();
- ptr_.dir_ = new resource_directory(dir);
- includes_data_ = false;
-}
-
-//Default constructor
-resource_directory::resource_directory()
- :characteristics_(0),
- timestamp_(0),
- major_version_(0), minor_version_(0),
- number_of_named_entries_(0), number_of_id_entries_(0)
-{}
-
-//Constructor from data
-resource_directory::resource_directory(const image_resource_directory& dir)
- :characteristics_(dir.Characteristics),
- timestamp_(dir.TimeDateStamp),
- major_version_(dir.MajorVersion), minor_version_(dir.MinorVersion),
- number_of_named_entries_(0), number_of_id_entries_(0) //Set to zero here, calculate on add
-{}
-
-//Returns characteristics of directory
-uint32_t resource_directory::get_characteristics() const
-{
- return characteristics_;
-}
-
-//Returns date and time stamp of directory
-uint32_t resource_directory::get_timestamp() const
-{
- return timestamp_;
-}
-
-//Returns major version of directory
-uint16_t resource_directory::get_major_version() const
-{
- return major_version_;
-}
-
-//Returns minor version of directory
-uint16_t resource_directory::get_minor_version() const
-{
- return minor_version_;
-}
-
-//Returns number of named entries
-uint32_t resource_directory::get_number_of_named_entries() const
-{
- return number_of_named_entries_;
-}
-
-//Returns number of ID entries
-uint32_t resource_directory::get_number_of_id_entries() const
-{
- return number_of_id_entries_;
-}
-
-//Returns resource_directory_entry array
-const resource_directory::entry_list& resource_directory::get_entry_list() const
-{
- return entries_;
-}
-
-//Returns resource_directory_entry array
-resource_directory::entry_list& resource_directory::get_entry_list()
-{
- return entries_;
-}
-
-//Adds resource_directory_entry
-void resource_directory::add_resource_directory_entry(const resource_directory_entry& entry)
-{
- entries_.push_back(entry);
- if(entry.is_named())
- ++number_of_named_entries_;
- else
- ++number_of_id_entries_;
-}
-
-//Clears resource_directory_entry array
-void resource_directory::clear_resource_directory_entry_list()
-{
- entries_.clear();
- number_of_named_entries_ = 0;
- number_of_id_entries_ = 0;
-}
-
-//Sets characteristics of directory
-void resource_directory::set_characteristics(uint32_t characteristics)
-{
- characteristics_ = characteristics;
-}
-
-//Sets date and time stamp of directory
-void resource_directory::set_timestamp(uint32_t timestamp)
-{
- timestamp_ = timestamp;
-}
-
-//Sets number of named entries
-void resource_directory::set_number_of_named_entries(uint32_t number)
-{
- number_of_named_entries_ = number;
-}
-
-//Sets number of ID entries
-void resource_directory::set_number_of_id_entries(uint32_t number)
-{
- number_of_id_entries_ = number;
-}
-
-//Sets major version of directory
-void resource_directory::set_major_version(uint16_t major_version)
-{
- major_version_ = major_version;
-}
-
-//Sets minor version of directory
-void resource_directory::get_minor_version(uint16_t minor_version)
-{
- minor_version_ = minor_version;
-}
-
-//Processes resource directory
-const resource_directory process_resource_directory(const pe_base& pe, uint32_t res_rva, uint32_t offset_to_directory, std::set<uint32_t>& processed)
-{
- resource_directory ret;
-
- //Check for resource loops
- if(!processed.insert(offset_to_directory).second)
- throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory);
-
- if(!pe_utils::is_sum_safe(res_rva, offset_to_directory))
- throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory);
-
- //Get root IMAGE_RESOURCE_DIRECTORY
- image_resource_directory directory = pe.section_data_from_rva<image_resource_directory>(res_rva + offset_to_directory, section_data_virtual, true);
-
- ret = resource_directory(directory);
-
- //Check DWORDs for possible overflows
- if(!pe_utils::is_sum_safe(directory.NumberOfIdEntries, directory.NumberOfNamedEntries)
- || directory.NumberOfIdEntries + directory.NumberOfNamedEntries >= pe_utils::max_dword / sizeof(image_resource_directory_entry) + sizeof(image_resource_directory))
- throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory);
-
- if(!pe_utils::is_sum_safe(offset_to_directory, sizeof(image_resource_directory) + (directory.NumberOfIdEntries + directory.NumberOfNamedEntries) * sizeof(image_resource_directory_entry))
- || !pe_utils::is_sum_safe(res_rva, offset_to_directory + sizeof(image_resource_directory) + (directory.NumberOfIdEntries + directory.NumberOfNamedEntries) * sizeof(image_resource_directory_entry)))
- throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory);
-
- for(unsigned long i = 0; i != static_cast<unsigned long>(directory.NumberOfIdEntries) + directory.NumberOfNamedEntries; ++i)
- {
- //Read directory entries one by one
- image_resource_directory_entry dir_entry = pe.section_data_from_rva<image_resource_directory_entry>(
- res_rva + sizeof(image_resource_directory) + i * sizeof(image_resource_directory_entry) + offset_to_directory, section_data_virtual, true);
-
- //Create directory entry structure
- resource_directory_entry entry;
-
- //If directory is named
- if(dir_entry.NameIsString)
- {
- if(!pe_utils::is_sum_safe(res_rva + sizeof(uint16_t) /* safe */, dir_entry.NameOffset))
- throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory);
-
- //get directory name length
- uint16_t directory_name_length = pe.section_data_from_rva<uint16_t>(res_rva + dir_entry.NameOffset, section_data_virtual, true);
-
- //Check name length
- if(pe.section_data_length_from_rva(res_rva + dir_entry.NameOffset + sizeof(uint16_t), res_rva + dir_entry.NameOffset + sizeof(uint16_t), section_data_virtual, true)
- < directory_name_length)
- throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory);
-
-#ifdef PE_BLISS_WINDOWS
- //Set entry UNICODE name
- entry.set_name(std::wstring(
- reinterpret_cast<const wchar_t*>(pe.section_data_from_rva(res_rva + dir_entry.NameOffset + sizeof(uint16_t), section_data_virtual, true)),
- directory_name_length));
-#else
- //Set entry UNICODE name
- entry.set_name(pe_utils::from_ucs2(u16string(
- reinterpret_cast<const unicode16_t*>(pe.section_data_from_rva(res_rva + dir_entry.NameOffset + sizeof(uint16_t), section_data_virtual, true)),
- directory_name_length)));
-#endif
- }
- else
- {
- //Else - set directory ID
- entry.set_id(dir_entry.Id);
- }
-
- //If directory entry has another resource directory
- if(dir_entry.DataIsDirectory)
- {
- entry.add_resource_directory(process_resource_directory(pe, res_rva, dir_entry.OffsetToDirectory, processed));
- }
- else
- {
- //If directory entry has data
- image_resource_data_entry data_entry = pe.section_data_from_rva<image_resource_data_entry>(
- res_rva + dir_entry.OffsetToData, section_data_virtual, true);
-
- //Check byte count that stated by data entry
- if(pe.section_data_length_from_rva(data_entry.OffsetToData, data_entry.OffsetToData, section_data_virtual, true) < data_entry.Size)
- throw pe_exception("Incorrect resource directory", pe_exception::incorrect_resource_directory);
-
- //Add data entry to directory entry
- entry.add_data_entry(resource_data_entry(
- std::string(pe.section_data_from_rva(data_entry.OffsetToData, section_data_virtual, true), data_entry.Size),
- data_entry.CodePage));
- }
-
- //Save directory entry
- ret.add_resource_directory_entry(entry);
- }
-
- //Return resource directory
- return ret;
-}
-
-//Helper function to calculate needed space for resource data
-void calculate_resource_data_space(const resource_directory& root, uint32_t aligned_offset_from_section_start, uint32_t& needed_size_for_structures, uint32_t& needed_size_for_strings)
-{
- needed_size_for_structures += sizeof(image_resource_directory);
- for(resource_directory::entry_list::const_iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it)
- {
- needed_size_for_structures += sizeof(image_resource_directory_entry);
-
- if((*it).is_named())
- needed_size_for_strings += static_cast<uint32_t>(((*it).get_name().length() + 1) * 2 /* unicode */ + sizeof(uint16_t) /* for string length */);
-
- if(!(*it).includes_data())
- calculate_resource_data_space((*it).get_resource_directory(), aligned_offset_from_section_start, needed_size_for_structures, needed_size_for_strings);
- }
-}
-
-//Helper function to calculate needed space for resource data
-void calculate_resource_data_space(const resource_directory& root, uint32_t needed_size_for_structures, uint32_t needed_size_for_strings, uint32_t& needed_size_for_data, uint32_t& current_data_pos)
-{
- for(resource_directory::entry_list::const_iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it)
- {
- if((*it).includes_data())
- {
- uint32_t data_size = static_cast<uint32_t>((*it).get_data_entry().get_data().length()
- + sizeof(image_resource_data_entry)
- + (pe_utils::align_up(current_data_pos, sizeof(uint32_t)) - current_data_pos) /* alignment */);
- needed_size_for_data += data_size;
- current_data_pos += data_size;
- }
- else
- {
- calculate_resource_data_space((*it).get_resource_directory(), needed_size_for_structures, needed_size_for_strings, needed_size_for_data, current_data_pos);
- }
- }
-}
-
-//Helper: sorts resource directory entries
-struct entry_sorter
-{
-public:
- bool operator()(const resource_directory_entry& entry1, const resource_directory_entry& entry2) const;
-};
-
-//Helper function to rebuild resource directory
-void rebuild_resource_directory(pe_base& pe, section& resource_section, resource_directory& root, uint32_t& current_structures_pos, uint32_t& current_data_pos, uint32_t& current_strings_pos, uint32_t offset_from_section_start)
-{
- //Create resource directory
- image_resource_directory dir = {0};
- dir.Characteristics = root.get_characteristics();
- dir.MajorVersion = root.get_major_version();
- dir.MinorVersion = root.get_minor_version();
- dir.TimeDateStamp = root.get_timestamp();
-
- {
- resource_directory::entry_list& entries = root.get_entry_list();
- std::sort(entries.begin(), entries.end(), entry_sorter());
- }
-
- //Calculate number of named and ID entries
- for(resource_directory::entry_list::const_iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it)
- {
- if((*it).is_named())
- ++dir.NumberOfNamedEntries;
- else
- ++dir.NumberOfIdEntries;
- }
-
- std::string& raw_data = resource_section.get_raw_data();
-
- //Save resource directory
- memcpy(&raw_data[current_structures_pos], &dir, sizeof(dir));
- current_structures_pos += sizeof(dir);
-
- uint32_t this_current_structures_pos = current_structures_pos;
-
- current_structures_pos += sizeof(image_resource_directory_entry) * (dir.NumberOfNamedEntries + dir.NumberOfIdEntries);
-
- //Create all resource directory entries
- for(resource_directory::entry_list::iterator it = root.get_entry_list().begin(); it != root.get_entry_list().end(); ++it)
- {
- image_resource_directory_entry entry;
- if((*it).is_named())
- {
- entry.Name = 0x80000000 | (current_strings_pos - offset_from_section_start);
- uint16_t unicode_length = static_cast<uint16_t>((*it).get_name().length());
- memcpy(&raw_data[current_strings_pos], &unicode_length, sizeof(unicode_length));
- current_strings_pos += sizeof(unicode_length);
-
-#ifdef PE_BLISS_WINDOWS
- memcpy(&raw_data[current_strings_pos], (*it).get_name().c_str(), (*it).get_name().length() * sizeof(uint16_t) + sizeof(uint16_t) /* unicode */);
-#else
- {
- u16string str(pe_utils::to_ucs2((*it).get_name()));
- memcpy(&raw_data[current_strings_pos], str.c_str(), (*it).get_name().length() * sizeof(uint16_t) + sizeof(uint16_t) /* unicode */);
- }
-#endif
-
- current_strings_pos += static_cast<unsigned long>((*it).get_name().length() * sizeof(uint16_t) + sizeof(uint16_t) /* unicode */);
- }
- else
- {
- entry.Name = (*it).get_id();
- }
-
- if((*it).includes_data())
- {
- current_data_pos = pe_utils::align_up(current_data_pos, sizeof(uint32_t));
- image_resource_data_entry data_entry = {0};
- data_entry.CodePage = (*it).get_data_entry().get_codepage();
- data_entry.Size = static_cast<uint32_t>((*it).get_data_entry().get_data().length());
- data_entry.OffsetToData = pe.rva_from_section_offset(resource_section, current_data_pos + sizeof(data_entry));
-
- entry.OffsetToData = current_data_pos - offset_from_section_start;
-
- memcpy(&raw_data[current_data_pos], &data_entry, sizeof(data_entry));
- current_data_pos += sizeof(data_entry);
-
- memcpy(&raw_data[current_data_pos], (*it).get_data_entry().get_data().data(), data_entry.Size);
- current_data_pos += data_entry.Size;
-
- memcpy(&raw_data[this_current_structures_pos], &entry, sizeof(entry));
- this_current_structures_pos += sizeof(entry);
- }
- else
- {
- entry.OffsetToData = 0x80000000 | (current_structures_pos - offset_from_section_start);
-
- memcpy(&raw_data[this_current_structures_pos], &entry, sizeof(entry));
- this_current_structures_pos += sizeof(entry);
-
- rebuild_resource_directory(pe, resource_section, (*it).get_resource_directory(), current_structures_pos, current_data_pos, current_strings_pos, offset_from_section_start);
- }
- }
-}
-
-//Helper function to rebuild resource directory
-bool entry_sorter::operator()(const resource_directory_entry& entry1, const resource_directory_entry& entry2) const
-{
- if(entry1.is_named() && entry2.is_named())
- return entry1.get_name() < entry2.get_name();
- else if(!entry1.is_named() && !entry2.is_named())
- return entry1.get_id() < entry2.get_id();
- else
- return entry1.is_named();
-}
-
-//Resources rebuilder
-//resource_directory - root resource directory
-//resources_section - section where resource directory will be placed (must be attached to PE image)
-//offset_from_section_start - offset from resources_section raw data start
-//resource_directory is non-constant, because it will be sorted
-//save_to_pe_headers - if true, new resource directory information will be saved to PE image headers
-//auto_strip_last_section - if true and resources are placed in the last section, it will be automatically stripped
-//number_of_id_entries and number_of_named_entries for resource directories are recalculated and not used
-const image_directory rebuild_resources(pe_base& pe, resource_directory& info, section& resources_section, uint32_t offset_from_section_start, bool save_to_pe_header, bool auto_strip_last_section)
-{
- //Check that resources_section is attached to this PE image
- if(!pe.section_attached(resources_section))
- throw pe_exception("Resource section must be attached to PE file", pe_exception::section_is_not_attached);
-
- //Check resource directory correctness
- if(info.get_entry_list().empty())
- throw pe_exception("Empty resource directory", pe_exception::incorrect_resource_directory);
-
- uint32_t aligned_offset_from_section_start = pe_utils::align_up(offset_from_section_start, sizeof(uint32_t));
- uint32_t needed_size_for_structures = aligned_offset_from_section_start - offset_from_section_start; //Calculate needed size for resource tables and data
- uint32_t needed_size_for_strings = 0;
- uint32_t needed_size_for_data = 0;
-
- calculate_resource_data_space(info, aligned_offset_from_section_start, needed_size_for_structures, needed_size_for_strings);
-
- {
- uint32_t current_data_pos = aligned_offset_from_section_start + needed_size_for_structures + needed_size_for_strings;
- calculate_resource_data_space(info, needed_size_for_structures, needed_size_for_strings, needed_size_for_data, current_data_pos);
- }
-
- uint32_t needed_size = needed_size_for_structures + needed_size_for_strings + needed_size_for_data;
-
- //Check if resources_section is last one. If it's not, check if there's enough place for resource data
- if(&resources_section != &*(pe.get_image_sections().end() - 1) &&
- (resources_section.empty() || pe_utils::align_up(resources_section.get_size_of_raw_data(), pe.get_file_alignment())
- < needed_size + aligned_offset_from_section_start))
- throw pe_exception("Insufficient space for resource directory", pe_exception::insufficient_space);
-
- std::string& raw_data = resources_section.get_raw_data();
-
- //This will be done only if resources_section is the last section of image or for section with unaligned raw length of data
- if(raw_data.length() < needed_size + aligned_offset_from_section_start)
- raw_data.resize(needed_size + aligned_offset_from_section_start); //Expand section raw data
-
- uint32_t current_structures_pos = aligned_offset_from_section_start;
- uint32_t current_strings_pos = current_structures_pos + needed_size_for_structures;
- uint32_t current_data_pos = current_strings_pos + needed_size_for_strings;
- rebuild_resource_directory(pe, resources_section, info, current_structures_pos, current_data_pos, current_strings_pos, aligned_offset_from_section_start);
-
- //Adjust section raw and virtual sizes
- pe.recalculate_section_sizes(resources_section, auto_strip_last_section);
-
- image_directory ret(pe.rva_from_section_offset(resources_section, aligned_offset_from_section_start), needed_size);
-
- //If auto-rewrite of PE headers is required
- if(save_to_pe_header)
- {
- pe.set_directory_rva(image_directory_entry_resource, ret.get_rva());
- pe.set_directory_size(image_directory_entry_resource, ret.get_size());
- }
-
- return ret;
-}
-
-//Returns resources from PE file
-const resource_directory get_resources(const pe_base& pe)
-{
- resource_directory ret;
-
- if(!pe.has_resources())
- return ret;
-
- //Get resource directory RVA
- uint32_t res_rva = pe.get_directory_rva(image_directory_entry_resource);
-
- //Store already processed directories to avoid resource loops
- std::set<uint32_t> processed;
-
- //Process all directories (recursion)
- ret = process_resource_directory(pe, res_rva, 0, processed);
-
- return ret;
-}
-
-//Finds resource_directory_entry by ID
-resource_directory::id_entry_finder::id_entry_finder(uint32_t id)
- :id_(id)
-{}
-
-bool resource_directory::id_entry_finder::operator()(const resource_directory_entry& entry) const
-{
- return !entry.is_named() && entry.get_id() == id_;
-}
-
-//Finds resource_directory_entry by name
-resource_directory::name_entry_finder::name_entry_finder(const std::wstring& name)
- :name_(name)
-{}
-
-bool resource_directory::name_entry_finder::operator()(const resource_directory_entry& entry) const
-{
- return entry.is_named() && entry.get_name() == name_;
-}
-
-//Finds resource_directory_entry by name or ID (universal)
-resource_directory::entry_finder::entry_finder(const std::wstring& name)
- :name_(name), named_(true)
-{}
-
-resource_directory::entry_finder::entry_finder(uint32_t id)
- :id_(id), named_(false)
-{}
-
-bool resource_directory::entry_finder::operator()(const resource_directory_entry& entry) const
-{
- if(named_)
- return entry.is_named() && entry.get_name() == name_;
- else
- return !entry.is_named() && entry.get_id() == id_;
-}
-
-//Returns resource_directory_entry by ID. If not found - throws an exception
-const resource_directory_entry& resource_directory::entry_by_id(uint32_t id) const
-{
- entry_list::const_iterator i = std::find_if(entries_.begin(), entries_.end(), id_entry_finder(id));
- if(i == entries_.end())
- throw pe_exception("Resource directory entry not found", pe_exception::resource_directory_entry_not_found);
-
- return *i;
-}
-
-//Returns resource_directory_entry by name. If not found - throws an exception
-const resource_directory_entry& resource_directory::entry_by_name(const std::wstring& name) const
-{
- entry_list::const_iterator i = std::find_if(entries_.begin(), entries_.end(), name_entry_finder(name));
- if(i == entries_.end())
- throw pe_exception("Resource directory entry not found", pe_exception::resource_directory_entry_not_found);
-
- return *i;
-}
-}
diff --git a/tools/pe_bliss/pe_resources.h b/tools/pe_bliss/pe_resources.h
deleted file mode 100644
index 1eb6437563..0000000000
--- a/tools/pe_bliss/pe_resources.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include <string>
-#include <set>
-#include "pe_structures.h"
-#include "pe_base.h"
-#include "pe_directory.h"
-
-namespace pe_bliss
-{
-//Class representing resource data entry
-class resource_data_entry
-{
-public:
- //Default constructor
- resource_data_entry();
- //Constructor from data
- resource_data_entry(const std::string& data, uint32_t codepage);
-
- //Returns resource data codepage
- uint32_t get_codepage() const;
- //Returns resource data
- const std::string& get_data() const;
-
-public: //These functions do not change everything inside image, they are used by PE class
- //You can also use them to rebuild resource directory
-
- //Sets resource data codepage
- void set_codepage(uint32_t codepage);
- //Sets resource data
- void set_data(const std::string& data);
-
-private:
- uint32_t codepage_; //Resource data codepage
- std::string data_; //Resource data
-};
-
-//Forward declaration
-class resource_directory;
-
-//Class representing resource directory entry
-class resource_directory_entry
-{
-public:
- //Default constructor
- resource_directory_entry();
- //Copy constructor
- resource_directory_entry(const resource_directory_entry& other);
- //Copy assignment operator
- resource_directory_entry& operator=(const resource_directory_entry& other);
-
- //Returns entry ID
- uint32_t get_id() const;
- //Returns entry name
- const std::wstring& get_name() const;
- //Returns true, if entry has name
- //Returns false, if entry has ID
- bool is_named() const;
-
- //Returns true, if entry includes resource_data_entry
- //Returns false, if entry includes resource_directory
- bool includes_data() const;
- //Returns resource_directory if entry includes it, otherwise throws an exception
- const resource_directory& get_resource_directory() const;
- //Returns resource_data_entry if entry includes it, otherwise throws an exception
- const resource_data_entry& get_data_entry() const;
-
- //Destructor
- ~resource_directory_entry();
-
-public: //These functions do not change everything inside image, they are used by PE class
- //You can also use them to rebuild resource directory
-
- //Sets entry name
- void set_name(const std::wstring& name);
- //Sets entry ID
- void set_id(uint32_t id);
-
- //Returns resource_directory if entry includes it, otherwise throws an exception
- resource_directory& get_resource_directory();
- //Returns resource_data_entry if entry includes it, otherwise throws an exception
- resource_data_entry& get_data_entry();
-
- //Adds resource_data_entry
- void add_data_entry(const resource_data_entry& entry);
- //Adds resource_directory
- void add_resource_directory(const resource_directory& dir);
-
-private:
- //Destroys included data
- void release();
-
-private:
- uint32_t id_;
- std::wstring name_;
-
- union includes
- {
- //Default constructor
- includes();
-
- //We use pointers, we're doing manual copying here
- class resource_data_entry* data_;
- class resource_directory* dir_; //We use pointer, because structs include each other
- };
-
- includes ptr_;
-
- bool includes_data_, named_;
-};
-
-//Class representing resource directory
-class resource_directory
-{
-public:
- typedef std::vector<resource_directory_entry> entry_list;
-
-public:
- //Default constructor
- resource_directory();
- //Constructor from data
- explicit resource_directory(const pe_win::image_resource_directory& dir);
-
- //Returns characteristics of directory
- uint32_t get_characteristics() const;
- //Returns date and time stamp of directory
- uint32_t get_timestamp() const;
- //Returns number of named entries
- uint32_t get_number_of_named_entries() const;
- //Returns number of ID entries
- uint32_t get_number_of_id_entries() const;
- //Returns major version of directory
- uint16_t get_major_version() const;
- //Returns minor version of directory
- uint16_t get_minor_version() const;
- //Returns resource_directory_entry array
- const entry_list& get_entry_list() const;
- //Returns resource_directory_entry by ID. If not found - throws an exception
- const resource_directory_entry& entry_by_id(uint32_t id) const;
- //Returns resource_directory_entry by name. If not found - throws an exception
- const resource_directory_entry& entry_by_name(const std::wstring& name) const;
-
-public: //These functions do not change everything inside image, they are used by PE class
- //You can also use them to rebuild resource directory
-
- //Adds resource_directory_entry
- void add_resource_directory_entry(const resource_directory_entry& entry);
- //Clears resource_directory_entry array
- void clear_resource_directory_entry_list();
-
- //Sets characteristics of directory
- void set_characteristics(uint32_t characteristics);
- //Sets date and time stamp of directory
- void set_timestamp(uint32_t timestamp);
- //Sets number of named entries
- void set_number_of_named_entries(uint32_t number);
- //Sets number of ID entries
- void set_number_of_id_entries(uint32_t number);
- //Sets major version of directory
- void set_major_version(uint16_t major_version);
- //Sets minor version of directory
- void get_minor_version(uint16_t minor_version);
-
- //Returns resource_directory_entry array
- entry_list& get_entry_list();
-
-private:
- uint32_t characteristics_;
- uint32_t timestamp_;
- uint16_t major_version_, minor_version_;
- uint32_t number_of_named_entries_, number_of_id_entries_;
- entry_list entries_;
-
-public: //Finder helpers
- //Finds resource_directory_entry by ID
- struct id_entry_finder
- {
- public:
- explicit id_entry_finder(uint32_t id);
- bool operator()(const resource_directory_entry& entry) const;
-
- private:
- uint32_t id_;
- };
-
- //Finds resource_directory_entry by name
- struct name_entry_finder
- {
- public:
- explicit name_entry_finder(const std::wstring& name);
- bool operator()(const resource_directory_entry& entry) const;
-
- private:
- std::wstring name_;
- };
-
- //Finds resource_directory_entry by name or ID (universal)
- struct entry_finder
- {
- public:
- explicit entry_finder(const std::wstring& name);
- explicit entry_finder(uint32_t id);
- bool operator()(const resource_directory_entry& entry) const;
-
- private:
- std::wstring name_;
- uint32_t id_;
- bool named_;
- };
-};
-
-//Returns resources (root resource_directory) from PE file
-const resource_directory get_resources(const pe_base& pe);
-
-//Resources rebuilder
-//resource_directory - root resource directory
-//resources_section - section where resource directory will be placed (must be attached to PE image)
-//resource_directory is non-constant, because it will be sorted
-//offset_from_section_start - offset from resources_section raw data start
-//save_to_pe_headers - if true, new resource directory information will be saved to PE image headers
-//auto_strip_last_section - if true and resources are placed in the last section, it will be automatically stripped
-//number_of_id_entries and number_of_named_entries for resource directories are recalculated and not used
-const image_directory rebuild_resources(pe_base& pe, resource_directory& info, section& resources_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-}
diff --git a/tools/pe_bliss/pe_rich_data.cpp b/tools/pe_bliss/pe_rich_data.cpp
deleted file mode 100644
index e92f7ddc1b..0000000000
--- a/tools/pe_bliss/pe_rich_data.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "pe_rich_data.h"
-
-namespace pe_bliss
-{
-//STUB OVERLAY
-//Default constructor
-rich_data::rich_data()
- :number_(0), version_(0), times_(0)
-{}
-
-//Who knows, what these fields mean...
-uint32_t rich_data::get_number() const
-{
- return number_;
-}
-
-uint32_t rich_data::get_version() const
-{
- return version_;
-}
-
-uint32_t rich_data::get_times() const
-{
- return times_;
-}
-
-void rich_data::set_number(uint32_t number)
-{
- number_ = number;
-}
-
-void rich_data::set_version(uint32_t version)
-{
- version_ = version;
-}
-
-void rich_data::set_times(uint32_t times)
-{
- times_ = times;
-}
-
-//Returns MSVC rich data
-const rich_data_list get_rich_data(const pe_base& pe)
-{
- //Returned value
- rich_data_list ret;
-
- const std::string& rich_overlay = pe.get_stub_overlay();
-
- //If there's no rich overlay, return empty vector
- if(rich_overlay.size() < sizeof(uint32_t))
- return ret;
-
- //True if rich data was found
- bool found = false;
-
- //Rich overlay ID ("Rich" word)
- static const uint32_t rich_overlay_id = 0x68636952;
-
- //Search for rich data overlay ID
- const char* begin = &rich_overlay[0];
- const char* end = begin + rich_overlay.length();
- for(; begin != end; ++begin)
- {
- if(*reinterpret_cast<const uint32_t*>(begin) == rich_overlay_id)
- {
- found = true; //We've found it!
- break;
- }
- }
-
- //If we found it
- if(found)
- {
- //Check remaining length
- if(static_cast<size_t>(end - begin) < sizeof(uint32_t))
- return ret;
-
- //The XOR key is after "Rich" word, we should get it
- uint32_t xorkey = *reinterpret_cast<const uint32_t*>(begin + sizeof(uint32_t));
-
- //True if rich data was found
- found = false;
-
- //Second search for signature "DanS"
- begin = &rich_overlay[0];
- for(; begin != end; ++begin)
- {
- if((*reinterpret_cast<const uint32_t*>(begin) ^ xorkey) == 0x536e6144) //"DanS"
- {
- found = true;
- break;
- }
- }
-
- //If second signature is found
- if(found)
- {
- begin += sizeof(uint32_t) * 3;
- //List all rich data structures
- while(begin < end)
- {
- begin += sizeof(uint32_t);
- if(begin >= end)
- break;
-
- //Check for rich overlay data end ("Rich" word reached)
- if(*reinterpret_cast<const uint32_t*>(begin) == rich_overlay_id)
- break;
-
- //Create rich_data structure
- rich_data data;
- data.set_number((*reinterpret_cast<const uint32_t*>(begin) ^ xorkey) >> 16);
- data.set_version((*reinterpret_cast<const uint32_t*>(begin) ^ xorkey) & 0xFFFF);
-
- begin += sizeof(uint32_t);
- if(begin >= end)
- break;
-
- data.set_times(*reinterpret_cast<const uint32_t*>(begin) ^ xorkey);
-
- //Save rich data structure
- ret.push_back(data);
- }
- }
- }
-
- //Return rich data structures list
- return ret;
-}
-}
diff --git a/tools/pe_bliss/pe_rich_data.h b/tools/pe_bliss/pe_rich_data.h
deleted file mode 100644
index 3e01d3c011..0000000000
--- a/tools/pe_bliss/pe_rich_data.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <vector>
-#include "pe_structures.h"
-#include "pe_base.h"
-
-namespace pe_bliss
-{
-//Rich data overlay class of Microsoft Visual Studio
-class rich_data
-{
-public:
- //Default constructor
- rich_data();
-
-public: //Getters
- //Who knows, what these fields mean...
- uint32_t get_number() const;
- uint32_t get_version() const;
- uint32_t get_times() const;
-
-public: //Setters, used by PE library only
- void set_number(uint32_t number);
- void set_version(uint32_t version);
- void set_times(uint32_t times);
-
-private:
- uint32_t number_;
- uint32_t version_;
- uint32_t times_;
-};
-
-//Rich data list typedef
-typedef std::vector<rich_data> rich_data_list;
-
-//Returns a vector with rich data (stub overlay)
-const rich_data_list get_rich_data(const pe_base& pe);
-}
diff --git a/tools/pe_bliss/pe_section.cpp b/tools/pe_bliss/pe_section.cpp
deleted file mode 100644
index 72127e22e2..0000000000
--- a/tools/pe_bliss/pe_section.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <algorithm>
-#include <string.h>
-#include "utils.h"
-#include "pe_section.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Section structure default constructor
-section::section()
- :old_size_(static_cast<size_t>(-1))
-{
- memset(&header_, 0, sizeof(image_section_header));
-}
-
-//Sets the name of section (8 characters maximum)
-void section::set_name(const std::string& name)
-{
- memset(header_.Name, 0, sizeof(header_.Name));
- memcpy(header_.Name, name.c_str(), std::min<size_t>(name.length(), sizeof(header_.Name)));
-}
-
-//Returns section name
-const std::string section::get_name() const
-{
- char buf[9] = {0};
- memcpy(buf, header_.Name, 8);
- return std::string(buf);
-}
-
-//Set flag (attribute) of section
-section& section::set_flag(uint32_t flag, bool setflag)
-{
- if(setflag)
- header_.Characteristics |= flag;
- else
- header_.Characteristics &= ~flag;
-
- return *this;
-}
-
-//Sets "readable" attribute of section
-section& section::readable(bool readable)
-{
- return set_flag(image_scn_mem_read, readable);
-}
-
-//Sets "writeable" attribute of section
-section& section::writeable(bool writeable)
-{
- return set_flag(image_scn_mem_write, writeable);
-}
-
-//Sets "executable" attribute of section
-section& section::executable(bool executable)
-{
- return set_flag(image_scn_mem_execute, executable);
-}
-
-//Sets "shared" attribute of section
-section& section::shared(bool shared)
-{
- return set_flag(image_scn_mem_shared, shared);
-}
-
-//Sets "discardable" attribute of section
-section& section::discardable(bool discardable)
-{
- return set_flag(image_scn_mem_discardable, discardable);
-}
-
-//Returns true if section is readable
-bool section::readable() const
-{
- return (header_.Characteristics & image_scn_mem_read) != 0;
-}
-
-//Returns true if section is writeable
-bool section::writeable() const
-{
- return (header_.Characteristics & image_scn_mem_write) != 0;
-}
-
-//Returns true if section is executable
-bool section::executable() const
-{
- return (header_.Characteristics & image_scn_mem_execute) != 0;
-}
-
-bool section::shared() const
-{
- return (header_.Characteristics & image_scn_mem_shared) != 0;
-}
-
-bool section::discardable() const
-{
- return (header_.Characteristics & image_scn_mem_discardable) != 0;
-}
-
-//Returns true if section has no RAW data
-bool section::empty() const
-{
- if(old_size_ != static_cast<size_t>(-1)) //If virtual memory is mapped, check raw data length (old_size_)
- return old_size_ == 0;
- else
- return raw_data_.empty();
-}
-
-//Returns raw section data from file image
-std::string& section::get_raw_data()
-{
- unmap_virtual();
- return raw_data_;
-}
-
-//Sets raw section data from file image
-void section::set_raw_data(const std::string& data)
-{
- old_size_ = static_cast<size_t>(-1);
- raw_data_ = data;
-}
-
-//Returns raw section data from file image
-const std::string& section::get_raw_data() const
-{
- unmap_virtual();
- return raw_data_;
-}
-
-//Returns mapped virtual section data
-const std::string& section::get_virtual_data(uint32_t section_alignment) const
-{
- map_virtual(section_alignment);
- return raw_data_;
-}
-
-//Returns mapped virtual section data
-std::string& section::get_virtual_data(uint32_t section_alignment)
-{
- map_virtual(section_alignment);
- return raw_data_;
-}
-
-//Maps virtual section data
-void section::map_virtual(uint32_t section_alignment) const
-{
- uint32_t aligned_virtual_size = get_aligned_virtual_size(section_alignment);
- if(old_size_ == static_cast<size_t>(-1) && aligned_virtual_size && aligned_virtual_size > raw_data_.length())
- {
- old_size_ = raw_data_.length();
- raw_data_.resize(aligned_virtual_size, 0);
- }
-}
-
-//Unmaps virtual section data
-void section::unmap_virtual() const
-{
- if(old_size_ != static_cast<size_t>(-1))
- {
- raw_data_.resize(old_size_, 0);
- old_size_ = static_cast<size_t>(-1);
- }
-}
-
-//Returns section virtual size
-uint32_t section::get_virtual_size() const
-{
- return header_.Misc.VirtualSize;
-}
-
-//Returns section virtual address
-uint32_t section::get_virtual_address() const
-{
- return header_.VirtualAddress;
-}
-
-//Returns size of section raw data
-uint32_t section::get_size_of_raw_data() const
-{
- return header_.SizeOfRawData;
-}
-
-//Returns pointer to raw section data in PE file
-uint32_t section::get_pointer_to_raw_data() const
-{
- return header_.PointerToRawData;
-}
-
-//Returns section characteristics
-uint32_t section::get_characteristics() const
-{
- return header_.Characteristics;
-}
-
-//Returns raw image section header
-const pe_win::image_section_header& section::get_raw_header() const
-{
- return header_;
-}
-
-//Returns raw image section header
-pe_win::image_section_header& section::get_raw_header()
-{
- return header_;
-}
-
-//Calculates aligned virtual section size
-uint32_t section::get_aligned_virtual_size(uint32_t section_alignment) const
-{
- if(get_size_of_raw_data())
- {
- if(!get_virtual_size())
- {
- //If section virtual size is zero
- //Set aligned virtual size of section as aligned raw size
- return pe_utils::align_up(get_size_of_raw_data(), section_alignment);
- }
- }
-
- return pe_utils::align_up(get_virtual_size(), section_alignment);
-}
-
-//Calculates aligned raw section size
-uint32_t section::get_aligned_raw_size(uint32_t file_alignment) const
-{
- if(get_size_of_raw_data())
- return pe_utils::align_up(get_size_of_raw_data(), file_alignment);
- else
- return 0;
-}
-
-//Sets size of raw section data
-void section::set_size_of_raw_data(uint32_t size_of_raw_data)
-{
- header_.SizeOfRawData = size_of_raw_data;
-}
-
-//Sets pointer to section raw data
-void section::set_pointer_to_raw_data(uint32_t pointer_to_raw_data)
-{
- header_.PointerToRawData = pointer_to_raw_data;
-}
-
-//Sets section characteristics
-void section::set_characteristics(uint32_t characteristics)
-{
- header_.Characteristics = characteristics;
-}
-
-//Sets section virtual size
-void section::set_virtual_size(uint32_t virtual_size)
-{
- header_.Misc.VirtualSize = virtual_size;
-}
-
-//Sets section virtual address
-void section::set_virtual_address(uint32_t virtual_address)
-{
- header_.VirtualAddress = virtual_address;
-}
-
-//Section by file offset finder helper (4gb max)
-section_by_raw_offset::section_by_raw_offset(uint32_t offset)
- :offset_(offset)
-{}
-
-bool section_by_raw_offset::operator()(const section& s) const
-{
- return (s.get_pointer_to_raw_data() <= offset_)
- && (s.get_pointer_to_raw_data() + s.get_size_of_raw_data() > offset_);
-}
-
-section_ptr_finder::section_ptr_finder(const section& s)
- :s_(s)
-{}
-
-bool section_ptr_finder::operator()(const section& s) const
-{
- return &s == &s_;
-}
-}
diff --git a/tools/pe_bliss/pe_section.h b/tools/pe_bliss/pe_section.h
deleted file mode 100644
index 617ecebe26..0000000000
--- a/tools/pe_bliss/pe_section.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include <vector>
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-//Enumeration of section data types, used in functions below
-enum section_data_type
-{
- section_data_raw,
- section_data_virtual
-};
-
-//Class representing image section
-class section
-{
-public:
- //Default constructor
- section();
-
- //Sets the name of section (stripped to 8 characters)
- void set_name(const std::string& name);
-
- //Returns the name of section
- const std::string get_name() const;
-
- //Changes attributes of section
- section& readable(bool readable);
- section& writeable(bool writeable);
- section& executable(bool executable);
- section& shared(bool shared);
- section& discardable(bool discardable);
-
- //Returns attributes of section
- bool readable() const;
- bool writeable() const;
- bool executable() const;
- bool shared() const;
- bool discardable() const;
-
- //Returns true if section has no RAW data
- bool empty() const;
-
- //Returns raw section data from file image
- std::string& get_raw_data();
- //Returns raw section data from file image
- const std::string& get_raw_data() const;
- //Returns mapped virtual section data
- const std::string& get_virtual_data(uint32_t section_alignment) const;
- //Returns mapped virtual section data
- std::string& get_virtual_data(uint32_t section_alignment);
-
-public: //Header getters
- //Returns section virtual size
- uint32_t get_virtual_size() const;
- //Returns section virtual address (RVA)
- uint32_t get_virtual_address() const;
- //Returns size of section raw data
- uint32_t get_size_of_raw_data() const;
- //Returns pointer to raw section data in PE file
- uint32_t get_pointer_to_raw_data() const;
- //Returns section characteristics
- uint32_t get_characteristics() const;
-
- //Returns raw image section header
- const pe_win::image_section_header& get_raw_header() const;
-
-public: //Aligned sizes calculation
- //Calculates aligned virtual section size
- uint32_t get_aligned_virtual_size(uint32_t section_alignment) const;
- //Calculates aligned raw section size
- uint32_t get_aligned_raw_size(uint32_t file_alignment) const;
-
-public: //Setters
- //Sets size of raw section data
- void set_size_of_raw_data(uint32_t size_of_raw_data);
- //Sets pointer to section raw data
- void set_pointer_to_raw_data(uint32_t pointer_to_raw_data);
- //Sets section characteristics
- void set_characteristics(uint32_t characteristics);
- //Sets raw section data from file image
- void set_raw_data(const std::string& data);
-
-public: //Setters, be careful
- //Sets section virtual size (doesn't set internal aligned virtual size, changes only header value)
- //Better use pe_base::set_section_virtual_size
- void set_virtual_size(uint32_t virtual_size);
- //Sets section virtual address
- void set_virtual_address(uint32_t virtual_address);
- //Returns raw image section header
- pe_win::image_section_header& get_raw_header();
-
-private:
- //Section header
- pe_win::image_section_header header_;
-
- //Maps virtual section data
- void map_virtual(uint32_t section_alignment) const;
-
- //Unmaps virtual section data
- void unmap_virtual() const;
-
- //Set flag (attribute) of section
- section& set_flag(uint32_t flag, bool setflag);
-
- //Old size of section (stored after mapping of virtual section memory)
- mutable std::size_t old_size_;
-
- //Section raw/virtual data
- mutable std::string raw_data_;
-};
-
-//Section by file offset finder helper (4gb max)
-struct section_by_raw_offset
-{
-public:
- explicit section_by_raw_offset(uint32_t offset);
- bool operator()(const section& s) const;
-
-private:
- uint32_t offset_;
-};
-
-//Helper: finder of section* in sections list
-struct section_ptr_finder
-{
-public:
- explicit section_ptr_finder(const section& s);
- bool operator()(const section& s) const;
-
-private:
- const section& s_;
-};
-
-typedef std::vector<section> section_list;
-}
diff --git a/tools/pe_bliss/pe_structures.h b/tools/pe_bliss/pe_structures.h
deleted file mode 100644
index efc99103b2..0000000000
--- a/tools/pe_bliss/pe_structures.h
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include <sstream>
-#include "stdint_defs.h"
-#if defined(_MSC_VER) or defined(__MINGW32__)
-#define PE_BLISS_WINDOWS
-#endif
-
-namespace pe_bliss
-{
-//Enumeration of PE types
-enum pe_type
-{
- pe_type_32,
- pe_type_64
-};
-
-namespace pe_win
-{
-const uint32_t image_numberof_directory_entries = 16;
-const uint32_t image_nt_optional_hdr32_magic = 0x10b;
-const uint32_t image_nt_optional_hdr64_magic = 0x20b;
-const uint32_t image_resource_name_is_string = 0x80000000;
-const uint32_t image_resource_data_is_directory = 0x80000000;
-
-const uint32_t image_dllcharacteristics_dynamic_base = 0x0040; // DLL can move.
-const uint32_t image_dllcharacteristics_force_integrity = 0x0080; // Code Integrity Image
-const uint32_t image_dllcharacteristics_nx_compat = 0x0100; // Image is NX compatible
-const uint32_t image_dllcharacteristics_no_isolation = 0x0200; // Image understands isolation and doesn't want it
-const uint32_t image_dllcharacteristics_no_seh = 0x0400; // Image does not use SEH. No SE handler may reside in this image
-const uint32_t image_dllcharacteristics_no_bind = 0x0800; // Do not bind this image.
-const uint32_t image_dllcharacteristics_wdm_driver = 0x2000; // Driver uses WDM model
-const uint32_t image_dllcharacteristics_terminal_server_aware = 0x8000;
-
-const uint32_t image_sizeof_file_header = 20;
-
-const uint32_t image_file_relocs_stripped = 0x0001; // Relocation info stripped from file.
-const uint32_t image_file_executable_image = 0x0002; // File is executable (i.e. no unresolved externel references).
-const uint32_t image_file_line_nums_stripped = 0x0004; // Line nunbers stripped from file.
-const uint32_t image_file_local_syms_stripped = 0x0008; // Local symbols stripped from file.
-const uint32_t image_file_aggresive_ws_trim = 0x0010; // Agressively trim working set
-const uint32_t image_file_large_address_aware = 0x0020; // App can handle >2gb addresses
-const uint32_t image_file_bytes_reversed_lo = 0x0080; // Bytes of machine word are reversed.
-const uint32_t image_file_32bit_machine = 0x0100; // 32 bit word machine.
-const uint32_t image_file_debug_stripped = 0x0200; // Debugging info stripped from file in .DBG file
-const uint32_t image_file_removable_run_from_swap = 0x0400; // If Image is on removable media, copy and run from the swap file.
-const uint32_t image_file_net_run_from_swap = 0x0800; // If Image is on Net, copy and run from the swap file.
-const uint32_t image_file_system = 0x1000; // System File.
-const uint32_t image_file_dll = 0x2000; // File is a DLL.
-const uint32_t image_file_up_system_only = 0x4000; // File should only be run on a UP machine
-const uint32_t image_file_bytes_reversed_hi = 0x8000; // Bytes of machine word are reversed.
-
-const uint32_t image_scn_lnk_nreloc_ovfl = 0x01000000; // Section contains extended relocations.
-const uint32_t image_scn_mem_discardable = 0x02000000; // Section can be discarded.
-const uint32_t image_scn_mem_not_cached = 0x04000000; // Section is not cachable.
-const uint32_t image_scn_mem_not_paged = 0x08000000; // Section is not pageable.
-const uint32_t image_scn_mem_shared = 0x10000000; // Section is shareable.
-const uint32_t image_scn_mem_execute = 0x20000000; // Section is executable.
-const uint32_t image_scn_mem_read = 0x40000000; // Section is readable.
-const uint32_t image_scn_mem_write = 0x80000000; // Section is writeable.
-
-const uint32_t image_scn_cnt_code = 0x00000020; // Section contains code.
-const uint32_t image_scn_cnt_initialized_data = 0x00000040; // Section contains initialized data.
-const uint32_t image_scn_cnt_uninitialized_data = 0x00000080; // Section contains uninitialized data.
-
-//Directory Entries
-const uint32_t image_directory_entry_export = 0; // Export Directory
-const uint32_t image_directory_entry_import = 1; // Import Directory
-const uint32_t image_directory_entry_resource = 2; // Resource Directory
-const uint32_t image_directory_entry_exception = 3; // Exception Directory
-const uint32_t image_directory_entry_security = 4; // Security Directory
-const uint32_t image_directory_entry_basereloc = 5; // Base Relocation Table
-const uint32_t image_directory_entry_debug = 6; // Debug Directory
-const uint32_t image_directory_entry_architecture = 7; // Architecture Specific Data
-const uint32_t image_directory_entry_globalptr = 8; // RVA of GP
-const uint32_t image_directory_entry_tls = 9; // TLS Directory
-const uint32_t image_directory_entry_load_config = 10; // Load Configuration Directory
-const uint32_t image_directory_entry_bound_import = 11; // Bound Import Directory in headers
-const uint32_t image_directory_entry_iat = 12; // Import Address Table
-const uint32_t image_directory_entry_delay_import = 13; // Delay Load Import Descriptors
-const uint32_t image_directory_entry_com_descriptor = 14; // COM Runtime descriptor
-
-//Subsystem Values
-const uint32_t image_subsystem_unknown = 0; // Unknown subsystem.
-const uint32_t image_subsystem_native = 1; // Image doesn't require a subsystem.
-const uint32_t image_subsystem_windows_gui = 2; // Image runs in the Windows GUI subsystem.
-const uint32_t image_subsystem_windows_cui = 3; // Image runs in the Windows character subsystem.
-const uint32_t image_subsystem_os2_cui = 5; // image runs in the OS/2 character subsystem.
-const uint32_t image_subsystem_posix_cui = 7; // image runs in the Posix character subsystem.
-const uint32_t image_subsystem_native_windows = 8; // image is a native Win9x driver.
-const uint32_t image_subsystem_windows_ce_gui = 9; // Image runs in the Windows CE subsystem.
-const uint32_t image_subsystem_efi_application = 10; //
-const uint32_t image_subsystem_efi_boot_service_driver = 11; //
-const uint32_t image_subsystem_efi_runtime_driver = 12; //
-const uint32_t image_subsystem_efi_rom = 13;
-const uint32_t image_subsystem_xbox = 14;
-const uint32_t image_subsystem_windows_boot_application = 16;
-
-//Imports
-const uint64_t image_ordinal_flag64 = 0x8000000000000000ull;
-const uint32_t image_ordinal_flag32 = 0x80000000;
-
-//Based relocation types
-const uint32_t image_rel_based_absolute = 0;
-const uint32_t image_rel_based_high = 1;
-const uint32_t image_rel_based_low = 2;
-const uint32_t image_rel_based_highlow = 3;
-const uint32_t image_rel_based_highadj = 4;
-const uint32_t image_rel_based_mips_jmpaddr = 5;
-const uint32_t image_rel_based_mips_jmpaddr16 = 9;
-const uint32_t image_rel_based_ia64_imm64 = 9;
-const uint32_t image_rel_based_dir64 = 10;
-
-//Exception directory
-//The function has an exception handler that should be called when looking for functions that need to examine exceptions
-const uint32_t unw_flag_ehandler = 0x01;
-//The function has a termination handler that should be called when unwinding an exception
-const uint32_t unw_flag_uhandler = 0x02;
-//This unwind info structure is not the primary one for the procedure.
-//Instead, the chained unwind info entry is the contents of a previous RUNTIME_FUNCTION entry.
-//If this flag is set, then the UNW_FLAG_EHANDLER and UNW_FLAG_UHANDLER flags must be cleared.
-//Also, the frame register and fixed-stack allocation fields must have the same values as in the primary unwind info
-const uint32_t unw_flag_chaininfo = 0x04;
-
-//Debug
-const uint32_t image_debug_misc_exename = 1;
-const uint32_t image_debug_type_unknown = 0;
-const uint32_t image_debug_type_coff = 1;
-const uint32_t image_debug_type_codeview = 2;
-const uint32_t image_debug_type_fpo = 3;
-const uint32_t image_debug_type_misc = 4;
-const uint32_t image_debug_type_exception = 5;
-const uint32_t image_debug_type_fixup = 6;
-const uint32_t image_debug_type_omap_to_src = 7;
-const uint32_t image_debug_type_omap_from_src = 8;
-const uint32_t image_debug_type_borland = 9;
-const uint32_t image_debug_type_reserved10 = 10;
-const uint32_t image_debug_type_clsid = 11;
-
-
-//Storage classes
-const uint32_t image_sym_class_end_of_function = static_cast<uint8_t>(-1);
-const uint32_t image_sym_class_null = 0x0000;
-const uint32_t image_sym_class_automatic = 0x0001;
-const uint32_t image_sym_class_external = 0x0002;
-const uint32_t image_sym_class_static = 0x0003;
-const uint32_t image_sym_class_register = 0x0004;
-const uint32_t image_sym_class_external_def = 0x0005;
-const uint32_t image_sym_class_label = 0x0006;
-const uint32_t image_sym_class_undefined_label = 0x0007;
-const uint32_t image_sym_class_member_of_struct = 0x0008;
-const uint32_t image_sym_class_argument = 0x0009;
-const uint32_t image_sym_class_struct_tag = 0x000a;
-const uint32_t image_sym_class_member_of_union = 0x000b;
-const uint32_t image_sym_class_union_tag = 0x000c;
-const uint32_t image_sym_class_type_definition = 0x000d;
-const uint32_t image_sym_class_undefined_static = 0x000e;
-const uint32_t image_sym_class_enum_tag = 0x000f;
-const uint32_t image_sym_class_member_of_enum = 0x0010;
-const uint32_t image_sym_class_register_param = 0x0011;
-const uint32_t image_sym_class_bit_field = 0x0012;
-
-const uint32_t image_sym_class_far_external = 0x0044;
-
-const uint32_t image_sym_class_block = 0x0064;
-const uint32_t image_sym_class_function = 0x0065;
-const uint32_t image_sym_class_end_of_struct = 0x0066;
-const uint32_t image_sym_class_file = 0x0067;
-
-const uint32_t image_sym_class_section = 0x0068;
-const uint32_t image_sym_class_weak_external = 0x0069;
-
-const uint32_t image_sym_class_clr_token = 0x006b;
-
-//type packing constants
-const uint32_t n_btmask = 0x000f;
-const uint32_t n_tmask = 0x0030;
-const uint32_t n_tmask1 = 0x00c0;
-const uint32_t n_tmask2 = 0x00f0;
-const uint32_t n_btshft = 4;
-const uint32_t n_tshift = 2;
-
-//Type (derived) values.
-const uint32_t image_sym_dtype_null = 0; // no derived type.
-const uint32_t image_sym_dtype_pointer = 1; // pointer.
-const uint32_t image_sym_dtype_function = 2; // function.
-const uint32_t image_sym_dtype_array = 3; // array.
-
-// Is x a function?
-//TODO
-#ifndef ISFCN
-#define ISFCN(x) (((x) & n_tmask) == (image_sym_dtype_function << n_btshft))
-#endif
-
-//Version info
-const uint32_t vs_ffi_fileflagsmask = 0x0000003FL;
-
-const uint32_t vs_ffi_signature = 0xFEEF04BDL;
-const uint32_t vs_ffi_strucversion = 0x00010000L;
-
-/* ----- VS_VERSION.dwFileFlags ----- */
-const uint32_t vs_ff_debug = 0x00000001L;
-const uint32_t vs_ff_prerelease = 0x00000002L;
-const uint32_t vs_ff_patched = 0x00000004L;
-const uint32_t vs_ff_privatebuild = 0x00000008L;
-const uint32_t vs_ff_infoinferred = 0x00000010L;
-const uint32_t vs_ff_specialbuild = 0x00000020L;
-
-/* ----- VS_VERSION.dwFileOS ----- */
-const uint32_t vos_unknown = 0x00000000L;
-const uint32_t vos_dos = 0x00010000L;
-const uint32_t vos_os216 = 0x00020000L;
-const uint32_t vos_os232 = 0x00030000L;
-const uint32_t vos_nt = 0x00040000L;
-const uint32_t vos_wince = 0x00050000L;
-
-const uint32_t vos__base = 0x00000000L;
-const uint32_t vos__windows16 = 0x00000001L;
-const uint32_t vos__pm16 = 0x00000002L;
-const uint32_t vos__pm32 = 0x00000003L;
-const uint32_t vos__windows32 = 0x00000004L;
-
-const uint32_t vos_dos_windows16 = 0x00010001L;
-const uint32_t vos_dos_windows32 = 0x00010004L;
-const uint32_t vos_os216_pm16 = 0x00020002L;
-const uint32_t vos_os232_pm32 = 0x00030003L;
-const uint32_t vos_nt_windows32 = 0x00040004L;
-
-/* ----- VS_VERSION.dwFileType ----- */
-const uint32_t vft_unknown = 0x00000000L;
-const uint32_t vft_app = 0x00000001L;
-const uint32_t vft_dll = 0x00000002L;
-const uint32_t vft_drv = 0x00000003L;
-const uint32_t vft_font = 0x00000004L;
-const uint32_t vft_vxd = 0x00000005L;
-const uint32_t vft_static_lib = 0x00000007L;
-
-const uint32_t message_resource_unicode = 0x0001;
-
-#pragma pack(push, 1)
-
-//Windows GUID structure
-struct guid
-{
- uint32_t Data1;
- uint16_t Data2;
- uint16_t Data3;
- uint8_t Data4[8];
-};
-
-//DOS .EXE header
-struct image_dos_header
-{
- uint16_t e_magic; // Magic number
- uint16_t e_cblp; // Bytes on last page of file
- uint16_t e_cp; // Pages in file
- uint16_t e_crlc; // Relocations
- uint16_t e_cparhdr; // Size of header in paragraphs
- uint16_t e_minalloc; // Minimum extra paragraphs needed
- uint16_t e_maxalloc; // Maximum extra paragraphs needed
- uint16_t e_ss; // Initial (relative) SS value
- uint16_t e_sp; // Initial SP value
- uint16_t e_csum; // Checksum
- uint16_t e_ip; // Initial IP value
- uint16_t e_cs; // Initial (relative) CS value
- uint16_t e_lfarlc; // File address of relocation table
- uint16_t e_ovno; // Overlay number
- uint16_t e_res[4]; // Reserved words
- uint16_t e_oemid; // OEM identifier (for e_oeminfo)
- uint16_t e_oeminfo; // OEM information; e_oemid specific
- uint16_t e_res2[10]; // Reserved words
- int32_t e_lfanew; // File address of new exe header
-};
-
-//Directory format
-struct image_data_directory
-{
- uint32_t VirtualAddress;
- uint32_t Size;
-};
-
-//Optional header format
-struct image_optional_header32
-{
- //Standard fields
- uint16_t Magic;
- uint8_t MajorLinkerVersion;
- uint8_t MinorLinkerVersion;
- uint32_t SizeOfCode;
- uint32_t SizeOfInitializedData;
- uint32_t SizeOfUninitializedData;
- uint32_t AddressOfEntryPoint;
- uint32_t BaseOfCode;
- uint32_t BaseOfData;
-
- //NT additional fields
- uint32_t ImageBase;
- uint32_t SectionAlignment;
- uint32_t FileAlignment;
- uint16_t MajorOperatingSystemVersion;
- uint16_t MinorOperatingSystemVersion;
- uint16_t MajorImageVersion;
- uint16_t MinorImageVersion;
- uint16_t MajorSubsystemVersion;
- uint16_t MinorSubsystemVersion;
- uint32_t Win32VersionValue;
- uint32_t SizeOfImage;
- uint32_t SizeOfHeaders;
- uint32_t CheckSum;
- uint16_t Subsystem;
- uint16_t DllCharacteristics;
- uint32_t SizeOfStackReserve;
- uint32_t SizeOfStackCommit;
- uint32_t SizeOfHeapReserve;
- uint32_t SizeOfHeapCommit;
- uint32_t LoaderFlags;
- uint32_t NumberOfRvaAndSizes;
- image_data_directory DataDirectory[image_numberof_directory_entries];
-};
-
-struct image_optional_header64
-{
- uint16_t Magic;
- uint8_t MajorLinkerVersion;
- uint8_t MinorLinkerVersion;
- uint32_t SizeOfCode;
- uint32_t SizeOfInitializedData;
- uint32_t SizeOfUninitializedData;
- uint32_t AddressOfEntryPoint;
- uint32_t BaseOfCode;
- uint64_t ImageBase;
- uint32_t SectionAlignment;
- uint32_t FileAlignment;
- uint16_t MajorOperatingSystemVersion;
- uint16_t MinorOperatingSystemVersion;
- uint16_t MajorImageVersion;
- uint16_t MinorImageVersion;
- uint16_t MajorSubsystemVersion;
- uint16_t MinorSubsystemVersion;
- uint32_t Win32VersionValue;
- uint32_t SizeOfImage;
- uint32_t SizeOfHeaders;
- uint32_t CheckSum;
- uint16_t Subsystem;
- uint16_t DllCharacteristics;
- uint64_t SizeOfStackReserve;
- uint64_t SizeOfStackCommit;
- uint64_t SizeOfHeapReserve;
- uint64_t SizeOfHeapCommit;
- uint32_t LoaderFlags;
- uint32_t NumberOfRvaAndSizes;
- image_data_directory DataDirectory[image_numberof_directory_entries];
-};
-
-struct image_file_header
-{
- uint16_t Machine;
- uint16_t NumberOfSections;
- uint32_t TimeDateStamp;
- uint32_t PointerToSymbolTable;
- uint32_t NumberOfSymbols;
- uint16_t SizeOfOptionalHeader;
- uint16_t Characteristics;
-};
-
-struct image_nt_headers64
-{
- uint32_t Signature;
- image_file_header FileHeader;
- image_optional_header64 OptionalHeader;
-};
-
-struct image_nt_headers32
-{
- uint32_t Signature;
- image_file_header FileHeader;
- image_optional_header32 OptionalHeader;
-};
-
-//Section header format
-struct image_section_header
-{
- uint8_t Name[8];
- union
- {
- uint32_t PhysicalAddress;
- uint32_t VirtualSize;
- } Misc;
-
- uint32_t VirtualAddress;
- uint32_t SizeOfRawData;
- uint32_t PointerToRawData;
- uint32_t PointerToRelocations;
- uint32_t PointerToLinenumbers;
- uint16_t NumberOfRelocations;
- uint16_t NumberOfLinenumbers;
- uint32_t Characteristics;
-};
-
-
-/// RESOURCES ///
-struct image_resource_directory
-{
- uint32_t Characteristics;
- uint32_t TimeDateStamp;
- uint16_t MajorVersion;
- uint16_t MinorVersion;
- uint16_t NumberOfNamedEntries;
- uint16_t NumberOfIdEntries;
- // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
-};
-
-struct vs_fixedfileinfo
-{
- uint32_t dwSignature; /* e.g. 0xfeef04bd */
- uint32_t dwStrucVersion; /* e.g. 0x00000042 = "0.42" */
- uint32_t dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */
- uint32_t dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */
- uint32_t dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */
- uint32_t dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */
- uint32_t dwFileFlagsMask; /* = 0x3F for version "0.42" */
- uint32_t dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */
- uint32_t dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */
- uint32_t dwFileType; /* e.g. VFT_DRIVER */
- uint32_t dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */
- uint32_t dwFileDateMS; /* e.g. 0 */
- uint32_t dwFileDateLS; /* e.g. 0 */
-};
-
-struct bitmapinfoheader
-{
- uint32_t biSize;
- int32_t biWidth;
- int32_t biHeight;
- uint16_t biPlanes;
- uint16_t biBitCount;
- uint32_t biCompression;
- uint32_t biSizeImage;
- int32_t biXPelsPerMeter;
- int32_t biYPelsPerMeter;
- uint32_t biClrUsed;
- uint32_t biClrImportant;
-};
-
-struct message_resource_entry
-{
- uint16_t Length;
- uint16_t Flags;
- uint8_t Text[1];
-};
-
-struct message_resource_block
-{
- uint32_t LowId;
- uint32_t HighId;
- uint32_t OffsetToEntries;
-};
-
-struct message_resource_data
-{
- uint32_t NumberOfBlocks;
- message_resource_block Blocks[1];
-};
-
-struct image_resource_directory_entry
-{
- union
- {
- struct
- {
- uint32_t NameOffset:31;
- uint32_t NameIsString:1;
- };
- uint32_t Name;
- uint16_t Id;
- };
-
- union
- {
- uint32_t OffsetToData;
- struct
- {
- uint32_t OffsetToDirectory:31;
- uint32_t DataIsDirectory:1;
- };
- };
-};
-
-struct image_resource_data_entry
-{
- uint32_t OffsetToData;
- uint32_t Size;
- uint32_t CodePage;
- uint32_t Reserved;
-};
-
-#pragma pack(push, 2)
-struct bitmapfileheader
-{
- uint16_t bfType;
- uint32_t bfSize;
- uint16_t bfReserved1;
- uint16_t bfReserved2;
- uint32_t bfOffBits;
-};
-#pragma pack(pop)
-
-
-
-//Structure representing ICON file header
-struct ico_header
-{
- uint16_t Reserved;
- uint16_t Type; //1
- uint16_t Count; //Count of icons included in icon group
-};
-
-//Structure that is stored in icon group directory in PE resources
-struct icon_group
-{
- uint8_t Width;
- uint8_t Height;
- uint8_t ColorCount;
- uint8_t Reserved;
- uint16_t Planes;
- uint16_t BitCount;
- uint32_t SizeInBytes;
- uint16_t Number; //Represents resource ID in PE icon list
-};
-
-//Structure representing ICON directory entry inside ICON file
-struct icondirentry
-{
- uint8_t Width;
- uint8_t Height;
- uint8_t ColorCount;
- uint8_t Reserved;
- uint16_t Planes;
- uint16_t BitCount;
- uint32_t SizeInBytes;
- uint32_t ImageOffset; //Offset from start of header to the image
-};
-
-//Structure representing CURSOR file header
-struct cursor_header
-{
- uint16_t Reserved;
- uint16_t Type; //2
- uint16_t Count; //Count of cursors included in cursor group
-};
-
-struct cursor_group
-{
- uint16_t Width;
- uint16_t Height; //Divide by 2 to get the actual height.
- uint16_t Planes;
- uint16_t BitCount;
- uint32_t SizeInBytes;
- uint16_t Number; //Represents resource ID in PE icon list
-};
-
-//Structure representing CURSOR directory entry inside CURSOR file
-struct cursordirentry
-{
- uint8_t Width; //Set to CURSOR_GROUP::Height/2.
- uint8_t Height;
- uint8_t ColorCount;
- uint8_t Reserved;
- uint16_t HotspotX;
- uint16_t HotspotY;
- uint32_t SizeInBytes;
- uint32_t ImageOffset; //Offset from start of header to the image
-};
-
-//Structure representing BLOCK in version info resource
-struct version_info_block //(always aligned on 32-bit (DWORD) boundary)
-{
- uint16_t Length; //Length of this block (doesn't include padding)
- uint16_t ValueLength; //Value length (if any)
- uint16_t Type; //Value type (0 = binary, 1 = text)
- uint16_t Key[1]; //Value name (block key) (always NULL terminated)
-
- //////////
- //WORD padding1[]; //Padding, if any (ALIGNMENT)
- //xxxxx Value[]; //Value data, if any (*ALIGNED*)
- //WORD padding2[]; //Padding, if any (ALIGNMENT)
- //xxxxx Child[]; //Child block(s), if any (*ALIGNED*)
- //////////
-};
-
-
-/// IMPORTS ///
-#pragma pack(push, 8)
-struct image_thunk_data64
-{
- union
- {
- uint64_t ForwarderString; // PBYTE
- uint64_t Function; // PDWORD
- uint64_t Ordinal;
- uint64_t AddressOfData; // PIMAGE_IMPORT_BY_NAME
- } u1;
-};
-#pragma pack(pop)
-
-struct image_thunk_data32
-{
- union
- {
- uint32_t ForwarderString; // PBYTE
- uint32_t Function; // PDWORD
- uint32_t Ordinal;
- uint32_t AddressOfData; // PIMAGE_IMPORT_BY_NAME
- } u1;
-};
-
-struct image_import_descriptor
-{
- union
- {
- uint32_t Characteristics; // 0 for terminating null import descriptor
- uint32_t OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
- };
-
- uint32_t TimeDateStamp; // 0 if not bound,
- // -1 if bound, and real date\time stamp
- // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
- // O.W. date/time stamp of DLL bound to (Old BIND)
-
- uint32_t ForwarderChain; // -1 if no forwarders
- uint32_t Name;
- uint32_t FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
-};
-
-
-/// TLS ///
-struct image_tls_directory64
-{
- uint64_t StartAddressOfRawData;
- uint64_t EndAddressOfRawData;
- uint64_t AddressOfIndex; // PDWORD
- uint64_t AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *;
- uint32_t SizeOfZeroFill;
- uint32_t Characteristics;
-};
-
-struct image_tls_directory32
-{
- uint32_t StartAddressOfRawData;
- uint32_t EndAddressOfRawData;
- uint32_t AddressOfIndex; // PDWORD
- uint32_t AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *
- uint32_t SizeOfZeroFill;
- uint32_t Characteristics;
-};
-
-
-/// Export Format ///
-struct image_export_directory
-{
- uint32_t Characteristics;
- uint32_t TimeDateStamp;
- uint16_t MajorVersion;
- uint16_t MinorVersion;
- uint32_t Name;
- uint32_t Base;
- uint32_t NumberOfFunctions;
- uint32_t NumberOfNames;
- uint32_t AddressOfFunctions; // RVA from base of image
- uint32_t AddressOfNames; // RVA from base of image
- uint32_t AddressOfNameOrdinals; // RVA from base of image
-};
-
-
-/// Based relocation format ///
-struct image_base_relocation
-{
- uint32_t VirtualAddress;
- uint32_t SizeOfBlock;
- // uint16_t TypeOffset[1];
-};
-
-
-/// New format import descriptors pointed to by DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ] ///
-struct image_bound_import_descriptor
-{
- uint32_t TimeDateStamp;
- uint16_t OffsetModuleName;
- uint16_t NumberOfModuleForwarderRefs;
- // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows
-};
-
-struct image_bound_forwarder_ref
-{
- uint32_t TimeDateStamp;
- uint16_t OffsetModuleName;
- uint16_t Reserved;
-};
-
-
-/// Exception directory ///
-struct image_runtime_function_entry
-{
- uint32_t BeginAddress;
- uint32_t EndAddress;
- uint32_t UnwindInfoAddress;
-};
-
-enum unwind_op_codes
-{
- uwop_push_nonvol = 0, /* info == register number */
- uwop_alloc_large, /* no info, alloc size in next 2 slots */
- uwop_alloc_small, /* info == size of allocation / 8 - 1 */
- uwop_set_fpreg, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
- uwop_save_nonvol, /* info == register number, offset in next slot */
- uwop_save_nonvol_far, /* info == register number, offset in next 2 slots */
- uwop_save_xmm128, /* info == XMM reg number, offset in next slot */
- uwop_save_xmm128_far, /* info == XMM reg number, offset in next 2 slots */
- uwop_push_machframe /* info == 0: no error-code, 1: error-code */
-};
-
-union unwind_code
-{
- struct s
- {
- uint8_t CodeOffset;
- uint8_t UnwindOp : 4;
- uint8_t OpInfo : 4;
- };
-
- uint16_t FrameOffset;
-};
-
-struct unwind_info
-{
- uint8_t Version : 3;
- uint8_t Flags : 5;
- uint8_t SizeOfProlog;
- uint8_t CountOfCodes;
- uint8_t FrameRegister : 4;
- uint8_t FrameOffset : 4;
- unwind_code UnwindCode[1];
- /* unwind_code MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
- * union {
- * OPTIONAL ULONG ExceptionHandler;
- * OPTIONAL ULONG FunctionEntry;
- * };
- * OPTIONAL ULONG ExceptionData[]; */
-};
-
-
-
-/// Debug ///
-struct image_debug_misc
-{
- uint32_t DataType; // type of misc data, see defines
- uint32_t Length; // total length of record, rounded to four
- // byte multiple.
- uint8_t Unicode; // TRUE if data is unicode string
- uint8_t Reserved[3];
- uint8_t Data[1]; // Actual data
-};
-
-struct image_coff_symbols_header
-{
- uint32_t NumberOfSymbols;
- uint32_t LvaToFirstSymbol;
- uint32_t NumberOfLinenumbers;
- uint32_t LvaToFirstLinenumber;
- uint32_t RvaToFirstByteOfCode;
- uint32_t RvaToLastByteOfCode;
- uint32_t RvaToFirstByteOfData;
- uint32_t RvaToLastByteOfData;
-};
-
-struct image_debug_directory
-{
- uint32_t Characteristics;
- uint32_t TimeDateStamp;
- uint16_t MajorVersion;
- uint16_t MinorVersion;
- uint32_t Type;
- uint32_t SizeOfData;
- uint32_t AddressOfRawData;
- uint32_t PointerToRawData;
-};
-
-
-#pragma pack(push, 2)
-struct image_symbol
-{
- union
- {
- uint8_t ShortName[8];
- struct
- {
- uint32_t Short; // if 0, use LongName
- uint32_t Long; // offset into string table
- } Name;
- uint32_t LongName[2]; // PBYTE [2]
- } N;
- uint32_t Value;
- int16_t SectionNumber;
- uint16_t Type;
- uint8_t StorageClass;
- uint8_t NumberOfAuxSymbols;
-};
-#pragma pack(pop)
-
-//CodeView Debug OMF signature. The signature at the end of the file is
-//a negative offset from the end of the file to another signature. At
-//the negative offset (base address) is another signature whose filepos
-//field points to the first OMFDirHeader in a chain of directories.
-//The NB05 signature is used by the link utility to indicated a completely
-//unpacked file. The NB06 signature is used by ilink to indicate that the
-//executable has had CodeView information from an incremental link appended
-//to the executable. The NB08 signature is used by cvpack to indicate that
-//the CodeView Debug OMF has been packed. CodeView will only process
-//executables with the NB08 signature.
-struct OMFSignature
-{
- char Signature[4]; // "NBxx"
- uint32_t filepos; // offset in file
-};
-
-struct CV_INFO_PDB20
-{
- OMFSignature CvHeader;
- uint32_t Signature;
- uint32_t Age;
- uint8_t PdbFileName[1];
-};
-
-struct CV_INFO_PDB70
-{
- uint32_t CvSignature;
- guid Signature;
- uint32_t Age;
- uint8_t PdbFileName[1];
-};
-
-// directory information structure
-// This structure contains the information describing the directory.
-// It is pointed to by the signature at the base address or the directory
-// link field of a preceeding directory. The directory entries immediately
-// follow this structure.
-struct OMFDirHeader
-{
- uint16_t cbDirHeader; // length of this structure
- uint16_t cbDirEntry; // number of bytes in each directory entry
- uint32_t cDir; // number of directorie entries
- int32_t lfoNextDir; // offset from base of next directory
- uint32_t flags; // status flags
-};
-
-// directory structure
-// The data in this structure is used to reference the data for each
-// subsection of the CodeView Debug OMF information. Tables that are
-// not associated with a specific module will have a module index of
-// oxffff. These tables are the global types table, the global symbol
-// table, the global public table and the library table.
-struct OMFDirEntry
-{
- uint16_t SubSection; // subsection type (sst...)
- uint16_t iMod; // module index
- int32_t lfo; // large file offset of subsection
- uint32_t cb; // number of bytes in subsection
-};
-
-
-/// CLR 2.0 header structure ///
-struct image_cor20_header
-{
- //Header versioning
- uint32_t cb;
- uint16_t MajorRuntimeVersion;
- uint16_t MinorRuntimeVersion;
-
- // Symbol table and startup information
- image_data_directory MetaData;
- uint32_t Flags;
-
- // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint.
- // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint.
- union
- {
- uint32_t EntryPointToken;
- uint32_t EntryPointRVA;
- };
-
- // Binding information
- image_data_directory Resources;
- image_data_directory StrongNameSignature;
-
- // Regular fixup and binding information
- image_data_directory CodeManagerTable;
- image_data_directory VTableFixups;
- image_data_directory ExportAddressTableJumps;
-
- // Precompiled image info (internal use only - set to zero)
- image_data_directory ManagedNativeHeader;
-};
-
-enum replaces_cor_hdr_numeric_defines
-{
- // COM+ Header entry point flags.
- comimage_flags_ilonly =0x00000001,
- comimage_flags_32bitrequired =0x00000002,
- comimage_flags_il_library =0x00000004,
- comimage_flags_strongnamesigned =0x00000008,
- comimage_flags_native_entrypoint =0x00000010,
- comimage_flags_trackdebugdata =0x00010000,
-
- // Version flags for image.
- cor_version_major_v2 =2,
- cor_version_major =cor_version_major_v2,
- cor_version_minor =0,
- cor_deleted_name_length =8,
- cor_vtablegap_name_length =8,
-
- // Maximum size of a NativeType descriptor.
- native_type_max_cb =1,
- cor_ilmethod_sect_small_max_datasize=0xff,
-
- // #defines for the MIH FLAGS
- image_cor_mih_methodrva =0x01,
- image_cor_mih_ehrva =0x02,
- image_cor_mih_basicblock =0x08,
-
- // V-table constants
- cor_vtable_32bit =0x01, // V-table slots are 32-bits in size.
- cor_vtable_64bit =0x02, // V-table slots are 64-bits in size.
- cor_vtable_from_unmanaged =0x04, // If set, transition from unmanaged.
- cor_vtable_from_unmanaged_retain_appdomain =0x08, // If set, transition from unmanaged with keeping the current appdomain.
- cor_vtable_call_most_derived =0x10, // Call most derived method described by
-
- // EATJ constants
- image_cor_eatj_thunk_size =32, // Size of a jump thunk reserved range.
-
- // Max name lengths
- //@todo: Change to unlimited name lengths.
- max_class_name =1024,
- max_package_name =1024
-};
-
-/// Load Configuration Directory Entry ///
-struct image_load_config_directory32
-{
- uint32_t Size;
- uint32_t TimeDateStamp;
- uint16_t MajorVersion;
- uint16_t MinorVersion;
- uint32_t GlobalFlagsClear;
- uint32_t GlobalFlagsSet;
- uint32_t CriticalSectionDefaultTimeout;
- uint32_t DeCommitFreeBlockThreshold;
- uint32_t DeCommitTotalFreeThreshold;
- uint32_t LockPrefixTable; // VA
- uint32_t MaximumAllocationSize;
- uint32_t VirtualMemoryThreshold;
- uint32_t ProcessHeapFlags;
- uint32_t ProcessAffinityMask;
- uint16_t CSDVersion;
- uint16_t Reserved1;
- uint32_t EditList; // VA
- uint32_t SecurityCookie; // VA
- uint32_t SEHandlerTable; // VA
- uint32_t SEHandlerCount;
-};
-
-struct image_load_config_directory64
-{
- uint32_t Size;
- uint32_t TimeDateStamp;
- uint16_t MajorVersion;
- uint16_t MinorVersion;
- uint32_t GlobalFlagsClear;
- uint32_t GlobalFlagsSet;
- uint32_t CriticalSectionDefaultTimeout;
- uint64_t DeCommitFreeBlockThreshold;
- uint64_t DeCommitTotalFreeThreshold;
- uint64_t LockPrefixTable; // VA
- uint64_t MaximumAllocationSize;
- uint64_t VirtualMemoryThreshold;
- uint64_t ProcessAffinityMask;
- uint32_t ProcessHeapFlags;
- uint16_t CSDVersion;
- uint16_t Reserved1;
- uint64_t EditList; // VA
- uint64_t SecurityCookie; // VA
- uint64_t SEHandlerTable; // VA
- uint64_t SEHandlerCount;
-};
-
-#pragma pack(pop)
-} //namespace pe_win
-
-#ifdef PE_BLISS_WINDOWS
-typedef wchar_t unicode16_t;
-typedef std::basic_string<unicode16_t> u16string;
-#else
-//Instead of wchar_t for windows
-typedef unsigned short unicode16_t;
-typedef std::basic_string<unicode16_t> u16string;
-#endif
-
-} //namespace pe_bliss
diff --git a/tools/pe_bliss/pe_tls.cpp b/tools/pe_bliss/pe_tls.cpp
deleted file mode 100644
index 5ec68e3f10..0000000000
--- a/tools/pe_bliss/pe_tls.cpp
+++ /dev/null
@@ -1,396 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "pe_tls.h"
-#include "pe_properties_generic.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//TLS
-//Default constructor
-tls_info::tls_info()
- :start_rva_(0), end_rva_(0), index_rva_(0), callbacks_rva_(0),
- size_of_zero_fill_(0), characteristics_(0)
-{}
-
-//Returns start RVA of TLS raw data
-uint32_t tls_info::get_raw_data_start_rva() const
-{
- return start_rva_;
-}
-
-//Returns end RVA of TLS raw data
-uint32_t tls_info::get_raw_data_end_rva() const
-{
- return end_rva_;
-}
-
-//Returns TLS index RVA
-uint32_t tls_info::get_index_rva() const
-{
- return index_rva_;
-}
-
-//Returns TLS callbacks RVA
-uint32_t tls_info::get_callbacks_rva() const
-{
- return callbacks_rva_;
-}
-
-//Returns size of zero fill
-uint32_t tls_info::get_size_of_zero_fill() const
-{
- return size_of_zero_fill_;
-}
-
-//Returns characteristics
-uint32_t tls_info::get_characteristics() const
-{
- return characteristics_;
-}
-
-//Returns raw TLS data
-const std::string& tls_info::get_raw_data() const
-{
- return raw_data_;
-}
-
-//Returns TLS callbacks addresses
-const tls_info::tls_callback_list& tls_info::get_tls_callbacks() const
-{
- return callbacks_;
-}
-
-//Returns TLS callbacks addresses
-tls_info::tls_callback_list& tls_info::get_tls_callbacks()
-{
- return callbacks_;
-}
-
-//Adds TLS callback
-void tls_info::add_tls_callback(uint32_t rva)
-{
- callbacks_.push_back(rva);
-}
-
-//Clears TLS callbacks list
-void tls_info::clear_tls_callbacks()
-{
- callbacks_.clear();
-}
-
-//Recalculates end address of raw TLS data
-void tls_info::recalc_raw_data_end_rva()
-{
- end_rva_ = static_cast<uint32_t>(start_rva_ + raw_data_.length());
-}
-
-//Sets start RVA of TLS raw data
-void tls_info::set_raw_data_start_rva(uint32_t rva)
-{
- start_rva_ = rva;
-}
-
-//Sets end RVA of TLS raw data
-void tls_info::set_raw_data_end_rva(uint32_t rva)
-{
- end_rva_ = rva;
-}
-
-//Sets TLS index RVA
-void tls_info::set_index_rva(uint32_t rva)
-{
- index_rva_ = rva;
-}
-
-//Sets TLS callbacks RVA
-void tls_info::set_callbacks_rva(uint32_t rva)
-{
- callbacks_rva_ = rva;
-}
-
-//Sets size of zero fill
-void tls_info::set_size_of_zero_fill(uint32_t size)
-{
- size_of_zero_fill_ = size;
-}
-
-//Sets characteristics
-void tls_info::set_characteristics(uint32_t characteristics)
-{
- characteristics_ = characteristics;
-}
-
-//Sets raw TLS data
-void tls_info::set_raw_data(const std::string& data)
-{
- raw_data_ = data;
-}
-
-//If image does not have TLS, throws an exception
-const tls_info get_tls_info(const pe_base& pe)
-{
- return pe.get_pe_type() == pe_type_32
- ? get_tls_info_base<pe_types_class_32>(pe)
- : get_tls_info_base<pe_types_class_64>(pe);
-}
-
-//TLS Rebuilder
-const image_directory rebuild_tls(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start, bool write_tls_callbacks, bool write_tls_data, tls_data_expand_type expand, bool save_to_pe_header, bool auto_strip_last_section)
-{
- return pe.get_pe_type() == pe_type_32
- ? rebuild_tls_base<pe_types_class_32>(pe, info, tls_section, offset_from_section_start, write_tls_callbacks, write_tls_data, expand, save_to_pe_header, auto_strip_last_section)
- : rebuild_tls_base<pe_types_class_64>(pe, info, tls_section, offset_from_section_start, write_tls_callbacks, write_tls_data, expand, save_to_pe_header, auto_strip_last_section);
-}
-
-//Get TLS info
-//If image does not have TLS, throws an exception
-template<typename PEClassType>
-const tls_info get_tls_info_base(const pe_base& pe)
-{
- tls_info ret;
-
- //If there's no TLS directory, throw an exception
- if(!pe.has_tls())
- throw pe_exception("Image does not have TLS directory", pe_exception::directory_does_not_exist);
-
- //Get TLS directory data
- typename PEClassType::TLSStruct tls_directory_data = pe.section_data_from_rva<typename PEClassType::TLSStruct>(pe.get_directory_rva(image_directory_entry_tls), section_data_virtual, true);
-
- //Check data addresses
- if(tls_directory_data.EndAddressOfRawData == tls_directory_data.StartAddressOfRawData)
- {
- try
- {
- pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.EndAddressOfRawData));
- }
- catch(const pe_exception&)
- {
- //Fix addressess on incorrect conversion
- tls_directory_data.EndAddressOfRawData = tls_directory_data.StartAddressOfRawData = 0;
- }
- }
-
- if(tls_directory_data.StartAddressOfRawData &&
- pe.section_data_length_from_va(static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData),
- static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData), section_data_virtual, true)
- < (tls_directory_data.EndAddressOfRawData - tls_directory_data.StartAddressOfRawData))
- throw pe_exception("Incorrect TLS directory", pe_exception::incorrect_tls_directory);
-
- //Fill TLS info
- //VAs are not checked
- ret.set_raw_data_start_rva(tls_directory_data.StartAddressOfRawData ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData)) : 0);
- ret.set_raw_data_end_rva(tls_directory_data.EndAddressOfRawData ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.EndAddressOfRawData)) : 0);
- ret.set_index_rva(tls_directory_data.AddressOfIndex ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.AddressOfIndex)) : 0);
- ret.set_callbacks_rva(tls_directory_data.AddressOfCallBacks ? pe.va_to_rva(static_cast<typename PEClassType::BaseSize>(tls_directory_data.AddressOfCallBacks)) : 0);
- ret.set_size_of_zero_fill(tls_directory_data.SizeOfZeroFill);
- ret.set_characteristics(tls_directory_data.Characteristics);
-
- if(tls_directory_data.StartAddressOfRawData && tls_directory_data.StartAddressOfRawData != tls_directory_data.EndAddressOfRawData)
- {
- //Read and save TLS RAW data
- ret.set_raw_data(std::string(
- pe.section_data_from_va(static_cast<typename PEClassType::BaseSize>(tls_directory_data.StartAddressOfRawData), section_data_virtual, true),
- static_cast<uint32_t>(tls_directory_data.EndAddressOfRawData - tls_directory_data.StartAddressOfRawData)));
- }
-
- //If file has TLS callbacks
- if(ret.get_callbacks_rva())
- {
- //Read callbacks VAs
- uint32_t current_tls_callback = 0;
-
- while(true)
- {
- //Read TLS callback VA
- typename PEClassType::BaseSize va = pe.section_data_from_va<typename PEClassType::BaseSize>(static_cast<typename PEClassType::BaseSize>(tls_directory_data.AddressOfCallBacks + current_tls_callback), section_data_virtual, true);
- if(va == 0)
- break;
-
- //Save it
- ret.add_tls_callback(pe.va_to_rva(va, false));
-
- //Move to next callback VA
- current_tls_callback += sizeof(va);
- }
- }
-
- return ret;
-}
-
-//Rebuilder of TLS structures
-//If write_tls_callbacks = true, TLS callbacks VAs will be written to their place
-//If write_tls_data = true, TLS data will be written to its place
-//If you have chosen to rewrite raw data, only (EndAddressOfRawData - StartAddressOfRawData) bytes will be written, not the full length of string
-//representing raw data content
-//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped
-//Note/TODO: TLS Callbacks array is not DWORD-aligned (seems to work on WinXP - Win7)
-template<typename PEClassType>
-const image_directory rebuild_tls_base(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start, bool write_tls_callbacks, bool write_tls_data, tls_data_expand_type expand, bool save_to_pe_header, bool auto_strip_last_section)
-{
- //Check that tls_section is attached to this PE image
- if(!pe.section_attached(tls_section))
- throw pe_exception("TLS section must be attached to PE file", pe_exception::section_is_not_attached);
-
- uint32_t tls_data_pos = pe_utils::align_up(offset_from_section_start, sizeof(typename PEClassType::BaseSize));
- uint32_t needed_size = sizeof(typename PEClassType::TLSStruct); //Calculate needed size for TLS table
-
- //Check if tls_section is last one. If it's not, check if there's enough place for TLS data
- if(&tls_section != &*(pe.get_image_sections().end() - 1) &&
- (tls_section.empty() || pe_utils::align_up(tls_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + tls_data_pos))
- throw pe_exception("Insufficient space for TLS directory", pe_exception::insufficient_space);
-
- //Check raw data positions
- if(info.get_raw_data_end_rva() < info.get_raw_data_start_rva() || info.get_index_rva() == 0)
- throw pe_exception("Incorrect TLS directory", pe_exception::incorrect_tls_directory);
-
- std::string& raw_data = tls_section.get_raw_data();
-
- //This will be done only if tls_section is the last section of image or for section with unaligned raw length of data
- if(raw_data.length() < needed_size + tls_data_pos)
- raw_data.resize(needed_size + tls_data_pos); //Expand section raw data
-
- //Create and fill TLS structure
- typename PEClassType::TLSStruct tls_struct = {0};
-
- typename PEClassType::BaseSize va;
- if(info.get_raw_data_start_rva())
- {
- pe.rva_to_va(info.get_raw_data_start_rva(), va);
- tls_struct.StartAddressOfRawData = va;
- tls_struct.SizeOfZeroFill = info.get_size_of_zero_fill();
- }
-
- if(info.get_raw_data_end_rva())
- {
- pe.rva_to_va(info.get_raw_data_end_rva(), va);
- tls_struct.EndAddressOfRawData = va;
- }
-
- pe.rva_to_va(info.get_index_rva(), va);
- tls_struct.AddressOfIndex = va;
-
- if(info.get_callbacks_rva())
- {
- pe.rva_to_va(info.get_callbacks_rva(), va);
- tls_struct.AddressOfCallBacks = va;
- }
-
- tls_struct.Characteristics = info.get_characteristics();
-
- //Save TLS structure
- memcpy(&raw_data[tls_data_pos], &tls_struct, sizeof(tls_struct));
-
- //If we are asked to rewrite TLS raw data
- if(write_tls_data && info.get_raw_data_start_rva() && info.get_raw_data_start_rva() != info.get_raw_data_end_rva())
- {
- try
- {
- //Check if we're going to write TLS raw data to an existing section (not to PE headers)
- section& raw_data_section = pe.section_from_rva(info.get_raw_data_start_rva());
- pe.expand_section(raw_data_section, info.get_raw_data_start_rva(), info.get_raw_data_end_rva() - info.get_raw_data_start_rva(), expand == tls_data_expand_raw ? pe_base::expand_section_raw : pe_base::expand_section_virtual);
- }
- catch(const pe_exception&)
- {
- //If no section is presented by StartAddressOfRawData, just go to next step
- }
-
- unsigned long write_raw_data_size = info.get_raw_data_end_rva() - info.get_raw_data_start_rva();
- unsigned long available_raw_length = 0;
-
- //Check if there's enough RAW space to write raw TLS data...
- if((available_raw_length = pe.section_data_length_from_rva(info.get_raw_data_start_rva(), info.get_raw_data_start_rva(), section_data_raw, true))
- < info.get_raw_data_end_rva() - info.get_raw_data_start_rva())
- {
- //Check if there's enough virtual space for it...
- if(pe.section_data_length_from_rva(info.get_raw_data_start_rva(), info.get_raw_data_start_rva(), section_data_virtual, true)
- < info.get_raw_data_end_rva() - info.get_raw_data_start_rva())
- throw pe_exception("Insufficient space for TLS raw data", pe_exception::insufficient_space);
- else
- write_raw_data_size = available_raw_length; //We'll write just a part of full raw data
- }
-
- //Write raw TLS data, if any
- if(write_raw_data_size != 0)
- memcpy(pe.section_data_from_rva(info.get_raw_data_start_rva(), true), info.get_raw_data().data(), write_raw_data_size);
- }
-
- //If we are asked to rewrite TLS callbacks addresses
- if(write_tls_callbacks && info.get_callbacks_rva())
- {
- unsigned long needed_callback_size = static_cast<unsigned long>((info.get_tls_callbacks().size() + 1 /* last null element */) * sizeof(typename PEClassType::BaseSize));
-
- try
- {
- //Check if we're going to write TLS callbacks VAs to an existing section (not to PE headers)
- section& raw_data_section = pe.section_from_rva(info.get_callbacks_rva());
- pe.expand_section(raw_data_section, info.get_callbacks_rva(), needed_callback_size, pe_base::expand_section_raw);
- }
- catch(const pe_exception&)
- {
- //If no section is presented by RVA of callbacks, just go to next step
- }
-
- //Check if there's enough space to write callbacks TLS data...
- if(pe.section_data_length_from_rva(info.get_callbacks_rva(), info.get_callbacks_rva(), section_data_raw, true)
- < needed_callback_size - sizeof(typename PEClassType::BaseSize) /* last zero element can be virtual only */)
- throw pe_exception("Insufficient space for TLS callbacks data", pe_exception::insufficient_space);
-
- if(pe.section_data_length_from_rva(info.get_callbacks_rva(), info.get_callbacks_rva(), section_data_virtual, true)
- < needed_callback_size /* check here full virtual data length available */)
- throw pe_exception("Insufficient space for TLS callbacks data", pe_exception::insufficient_space);
-
- std::vector<typename PEClassType::BaseSize> callbacks_virtual_addresses;
- callbacks_virtual_addresses.reserve(info.get_tls_callbacks().size() + 1 /* last null element */);
-
- //Convert TLS RVAs to VAs
- for(tls_info::tls_callback_list::const_iterator it = info.get_tls_callbacks().begin(); it != info.get_tls_callbacks().end(); ++it)
- {
- typename PEClassType::BaseSize cb_va = 0;
- pe.rva_to_va(*it, cb_va);
- callbacks_virtual_addresses.push_back(cb_va);
- }
-
- //Ending null element
- callbacks_virtual_addresses.push_back(0);
-
- //Write callbacks TLS data
- memcpy(pe.section_data_from_rva(info.get_callbacks_rva(), true), &callbacks_virtual_addresses[0], needed_callback_size);
- }
-
- //Adjust section raw and virtual sizes
- pe.recalculate_section_sizes(tls_section, auto_strip_last_section);
-
- image_directory ret(pe.rva_from_section_offset(tls_section, tls_data_pos), needed_size);
-
- //If auto-rewrite of PE headers is required
- if(save_to_pe_header)
- {
- pe.set_directory_rva(image_directory_entry_tls, ret.get_rva());
- pe.set_directory_size(image_directory_entry_tls, ret.get_size());
- }
-
- return ret;
-}
-}
diff --git a/tools/pe_bliss/pe_tls.h b/tools/pe_bliss/pe_tls.h
deleted file mode 100644
index 316e208147..0000000000
--- a/tools/pe_bliss/pe_tls.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <memory>
-#include <istream>
-#include "pe_base.h"
-#include "pe_directory.h"
-
-namespace pe_bliss
-{
-//Class representing TLS info
-//We use "DWORD" type to represent RVAs, because RVA is
-//always 32bit even in PE+
-class tls_info
-{
-public:
- typedef std::vector<uint32_t> tls_callback_list;
-
-public:
- //Default constructor
- tls_info();
-
- //Returns start RVA of TLS raw data
- uint32_t get_raw_data_start_rva() const;
- //Returns end RVA of TLS raw data
- uint32_t get_raw_data_end_rva() const;
- //Returns TLS index RVA
- uint32_t get_index_rva() const;
- //Returns TLS callbacks RVA
- uint32_t get_callbacks_rva() const;
- //Returns size of zero fill
- uint32_t get_size_of_zero_fill() const;
- //Returns characteristics
- uint32_t get_characteristics() const;
- //Returns raw TLS data
- const std::string& get_raw_data() const;
- //Returns TLS callbacks addresses
- const tls_callback_list& get_tls_callbacks() const;
-
-public: //These functions do not change everything inside image, they are used by PE class
- //You can also use them to rebuild TLS directory
-
- //Sets start RVA of TLS raw data
- void set_raw_data_start_rva(uint32_t rva);
- //Sets end RVA of TLS raw data
- void set_raw_data_end_rva(uint32_t rva);
- //Sets TLS index RVA
- void set_index_rva(uint32_t rva);
- //Sets TLS callbacks RVA
- void set_callbacks_rva(uint32_t rva);
- //Sets size of zero fill
- void set_size_of_zero_fill(uint32_t size);
- //Sets characteristics
- void set_characteristics(uint32_t characteristics);
- //Sets raw TLS data
- void set_raw_data(const std::string& data);
- //Returns TLS callbacks addresses
- tls_callback_list& get_tls_callbacks();
- //Adds TLS callback
- void add_tls_callback(uint32_t rva);
- //Clears TLS callbacks list
- void clear_tls_callbacks();
- //Recalculates end address of raw TLS data
- void recalc_raw_data_end_rva();
-
-private:
- uint32_t start_rva_, end_rva_, index_rva_, callbacks_rva_;
- uint32_t size_of_zero_fill_, characteristics_;
-
- //Raw TLS data
- std::string raw_data_;
-
- //TLS callback RVAs
- tls_callback_list callbacks_;
-};
-
-//Represents type of expanding of TLS section containing raw data
-//(Works only if you are writing TLS raw data to tls_section and it is the last one in the PE image on the moment of TLS rebuild)
-enum tls_data_expand_type
-{
- tls_data_expand_raw, //If there is not enough raw space for raw TLS data, it can be expanded
- tls_data_expand_virtual //If there is not enough virtual place for raw TLS data, it can be expanded
-};
-
-
-//Get TLS info
-//If image does not have TLS, throws an exception
-const tls_info get_tls_info(const pe_base& pe);
-
-template<typename PEClassType>
-const tls_info get_tls_info_base(const pe_base& pe);
-
-//Rebuilder of TLS structures
-//If write_tls_callbacks = true, TLS callbacks VAs will be written to their place
-//If write_tls_data = true, TLS data will be written to its place
-//If you have chosen to rewrite raw data, only (EndAddressOfRawData - StartAddressOfRawData) bytes will be written, not the full length of string
-//representing raw data content
-//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped
-const image_directory rebuild_tls(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start = 0, bool write_tls_callbacks = true, bool write_tls_data = true, tls_data_expand_type expand = tls_data_expand_raw, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-
-template<typename PEClassType>
-const image_directory rebuild_tls_base(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start = 0, bool write_tls_callbacks = true, bool write_tls_data = true, tls_data_expand_type expand = tls_data_expand_raw, bool save_to_pe_header = true, bool auto_strip_last_section = true);
-}
diff --git a/tools/pe_bliss/resource_bitmap_reader.cpp b/tools/pe_bliss/resource_bitmap_reader.cpp
deleted file mode 100644
index 3546461f53..0000000000
--- a/tools/pe_bliss/resource_bitmap_reader.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <cmath>
-#include "resource_bitmap_reader.h"
-#include "pe_resource_viewer.h"
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-resource_bitmap_reader::resource_bitmap_reader(const pe_resource_viewer& res)
- :res_(res)
-{}
-
-//Returns bitmap data by name and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_bitmap_reader::get_bitmap_by_name(const std::wstring& name, uint32_t index) const
-{
- return create_bitmap(res_.get_resource_data_by_name(pe_resource_viewer::resource_bitmap, name, index).get_data());
-}
-
-//Returns bitmap data by name and language (minimum checks of format correctness)
-const std::string resource_bitmap_reader::get_bitmap_by_name(uint32_t language, const std::wstring& name) const
-{
- return create_bitmap(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_bitmap, name).get_data());
-}
-
-//Returns bitmap data by ID and language (minimum checks of format correctness)
-const std::string resource_bitmap_reader::get_bitmap_by_id_lang(uint32_t language, uint32_t id) const
-{
- return create_bitmap(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_bitmap, id).get_data());
-}
-
-//Returns bitmap data by ID and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_bitmap_reader::get_bitmap_by_id(uint32_t id, uint32_t index) const
-{
- return create_bitmap(res_.get_resource_data_by_id(pe_resource_viewer::resource_bitmap, id, index).get_data());
-}
-
-//Helper function of creating bitmap header
-const std::string resource_bitmap_reader::create_bitmap(const std::string& resource_data)
-{
- //Create bitmap file header
- bitmapfileheader header = {0};
- header.bfType = 0x4d42; //Signature "BM"
- header.bfOffBits = sizeof(bitmapfileheader) + sizeof(bitmapinfoheader); //Offset to bitmap bits
- header.bfSize = static_cast<uint32_t>(sizeof(bitmapfileheader) + resource_data.length()); //Size of bitmap
-
- //Check size of resource data
- if(resource_data.length() < sizeof(bitmapinfoheader))
- throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap);
-
- {
- //Get bitmap info header
- const bitmapinfoheader* info = reinterpret_cast<const bitmapinfoheader*>(resource_data.data());
-
- //If color table is present, skip it
- if(info->biClrUsed != 0)
- header.bfOffBits += 4 * info->biClrUsed; //Add this size to offset to bitmap bits
- else if(info->biBitCount <= 8)
- header.bfOffBits += 4 * static_cast<uint32_t>(std::pow(2.f, info->biBitCount)); //Add this size to offset to bitmap bits
- }
-
- //Return final bitmap data
- return std::string(reinterpret_cast<const char*>(&header), sizeof(bitmapfileheader)) + resource_data;
-}
-}
diff --git a/tools/pe_bliss/resource_bitmap_reader.h b/tools/pe_bliss/resource_bitmap_reader.h
deleted file mode 100644
index f2b92bbde7..0000000000
--- a/tools/pe_bliss/resource_bitmap_reader.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-class pe_resource_viewer;
-
-class resource_bitmap_reader
-{
-public:
- resource_bitmap_reader(const pe_resource_viewer& res);
-
- //Returns bitmap data by name and language (minimum checks of format correctness)
- const std::string get_bitmap_by_name(uint32_t language, const std::wstring& name) const;
- //Returns bitmap data by name and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_bitmap_by_name(const std::wstring& name, uint32_t index = 0) const;
- //Returns bitmap data by ID and language (minimum checks of format correctness)
- const std::string get_bitmap_by_id_lang(uint32_t language, uint32_t id) const;
- //Returns bitmap data by ID and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_bitmap_by_id(uint32_t id, uint32_t index = 0) const;
-
-private:
- //Helper function of creating bitmap header
- static const std::string create_bitmap(const std::string& resource_data);
-
- const pe_resource_viewer& res_;
-};
-}
diff --git a/tools/pe_bliss/resource_bitmap_writer.cpp b/tools/pe_bliss/resource_bitmap_writer.cpp
deleted file mode 100644
index 3445a08445..0000000000
--- a/tools/pe_bliss/resource_bitmap_writer.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "resource_bitmap_writer.h"
-#include "pe_resource_manager.h"
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-resource_bitmap_writer::resource_bitmap_writer(pe_resource_manager& res)
- :res_(res)
-{}
-
-//Adds bitmap from bitmap file data. If bitmap already exists, replaces it
-//timestamp will be used for directories that will be added
-void resource_bitmap_writer::add_bitmap(const std::string& bitmap_file, uint32_t id, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- //Check bitmap data a little
- if(bitmap_file.length() < sizeof(bitmapfileheader))
- throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap);
-
- resource_directory_entry new_entry;
- new_entry.set_id(id);
-
- //Add bitmap
- res_.add_resource(bitmap_file.substr(sizeof(bitmapfileheader)), pe_resource_viewer::resource_bitmap, new_entry, resource_directory::entry_finder(id), language, codepage, timestamp);
-}
-
-//Adds bitmap from bitmap file data. If bitmap already exists, replaces it
-//timestamp will be used for directories that will be added
-void resource_bitmap_writer::add_bitmap(const std::string& bitmap_file, const std::wstring& name, uint32_t language, uint32_t codepage, uint32_t timestamp)
-{
- //Check bitmap data a little
- if(bitmap_file.length() < sizeof(bitmapfileheader))
- throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap);
-
- resource_directory_entry new_entry;
- new_entry.set_name(name);
-
- //Add bitmap
- res_.add_resource(bitmap_file.substr(sizeof(bitmapfileheader)), pe_resource_viewer::resource_bitmap, new_entry, resource_directory::entry_finder(name), language, codepage, timestamp);
-}
-
-//Removes bitmap by name/ID and language
-bool resource_bitmap_writer::remove_bitmap(const std::wstring& name, uint32_t language)
-{
- return res_.remove_resource(pe_resource_viewer::resource_bitmap, name, language);
-}
-
-//Removes bitmap by name/ID and language
-bool resource_bitmap_writer::remove_bitmap(uint32_t id, uint32_t language)
-{
- return res_.remove_resource(pe_resource_viewer::resource_bitmap, id, language);
-}
-}
diff --git a/tools/pe_bliss/resource_bitmap_writer.h b/tools/pe_bliss/resource_bitmap_writer.h
deleted file mode 100644
index 4b8ea72705..0000000000
--- a/tools/pe_bliss/resource_bitmap_writer.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-class pe_resource_manager;
-
-class resource_bitmap_writer
-{
-public:
- resource_bitmap_writer(pe_resource_manager& res);
-
- //Adds bitmap from bitmap file data. If bitmap already exists, replaces it
- //timestamp will be used for directories that will be added
- void add_bitmap(const std::string& bitmap_file, uint32_t id, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0);
- void add_bitmap(const std::string& bitmap_file, const std::wstring& name, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0);
-
- //Removes bitmap by name/ID and language
- bool remove_bitmap(const std::wstring& name, uint32_t language);
- bool remove_bitmap(uint32_t id, uint32_t language);
-
-private:
- pe_resource_manager& res_;
-};
-}
diff --git a/tools/pe_bliss/resource_cursor_icon_reader.cpp b/tools/pe_bliss/resource_cursor_icon_reader.cpp
deleted file mode 100644
index 28a259163e..0000000000
--- a/tools/pe_bliss/resource_cursor_icon_reader.cpp
+++ /dev/null
@@ -1,521 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <algorithm>
-#include "resource_cursor_icon_reader.h"
-#include "pe_structures.h"
-#include "pe_resource_viewer.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-resource_cursor_icon_reader::resource_cursor_icon_reader(const pe_resource_viewer& res)
- :res_(res)
-{}
-
-//Helper function of creating icon headers from ICON_GROUP resource data
-//Returns icon count
-uint16_t resource_cursor_icon_reader::format_icon_headers(std::string& ico_data, const std::string& resource_data)
-{
- //Check resource data size
- if(resource_data.length() < sizeof(ico_header))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- //Get icon header
- const ico_header* info = reinterpret_cast<const ico_header*>(resource_data.data());
-
- //Check resource data size
- if(resource_data.length() < sizeof(ico_header) + info->Count * sizeof(icon_group))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- //Reserve memory to speed up a little
- ico_data.reserve(sizeof(ico_header) + info->Count * sizeof(icondirentry));
- ico_data.append(reinterpret_cast<const char*>(info), sizeof(ico_header));
-
- //Iterate over all listed icons
- uint32_t offset = sizeof(ico_header) + sizeof(icondirentry) * info->Count;
- for(uint16_t i = 0; i != info->Count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(resource_data.data() + sizeof(ico_header) + i * sizeof(icon_group));
-
- //Fill icon data
- icondirentry direntry;
- direntry.BitCount = group->BitCount;
- direntry.ColorCount = group->ColorCount;
- direntry.Height = group->Height;
- direntry.Planes = group->Planes;
- direntry.Reserved = group->Reserved;
- direntry.SizeInBytes = group->SizeInBytes;
- direntry.Width = group->Width;
- direntry.ImageOffset = offset;
-
- //Add icon header to returned value
- ico_data.append(reinterpret_cast<const char*>(&direntry), sizeof(icondirentry));
-
- offset += group->SizeInBytes;
- }
-
- //Return icon count
- return info->Count;
-}
-
-//Returns single icon data by ID and language (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_single_icon_by_id_lang(uint32_t language, uint32_t id) const
-{
- //Get icon headers
- std::string icon_data(lookup_icon_group_data_by_icon(id, language));
- //Append icon data
- icon_data.append(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon, id).get_data());
- return icon_data;
-}
-
-//Returns single icon data by ID and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_single_icon_by_id(uint32_t id, uint32_t index) const
-{
- pe_resource_viewer::resource_language_list languages(res_.list_resource_languages(pe_resource_viewer::resource_icon, id));
- if(languages.size() <= index)
- throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found);
-
- //Get icon headers
- std::string icon_data(lookup_icon_group_data_by_icon(id, languages.at(index)));
- //Append icon data
- icon_data.append(res_.get_resource_data_by_id(pe_resource_viewer::resource_icon, id, index).get_data());
- return icon_data;
-}
-
-//Returns icon data by name and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_icon_by_name(const std::wstring& name, uint32_t index) const
-{
- std::string ret;
-
- //Get resource by name and index
- const std::string data = res_.get_resource_data_by_name(pe_resource_viewer::resource_icon_group, name, index).get_data();
-
- //Create icon headers
- uint16_t icon_count = format_icon_headers(ret, data);
-
- //Append icon data
- for(uint16_t i = 0; i != icon_count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group));
- ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_icon, group->Number, index).get_data();
- }
-
- return ret;
-}
-
-//Returns icon data by name and language (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_icon_by_name(uint32_t language, const std::wstring& name) const
-{
- std::string ret;
-
- //Get resource by name and language
- const std::string data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, name).get_data();
-
- //Create icon headers
- uint16_t icon_count = format_icon_headers(ret, data);
-
- //Append icon data
- for(uint16_t i = 0; i != icon_count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group));
- ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon, group->Number).get_data();
- }
-
- return ret;
-}
-
-//Returns icon data by ID and language (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_icon_by_id_lang(uint32_t language, uint32_t id) const
-{
- std::string ret;
-
- //Get resource by language and id
- const std::string data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, id).get_data();
-
- //Create icon headers
- uint16_t icon_count = format_icon_headers(ret, data);
-
- //Append icon data
- for(uint16_t i = 0; i != icon_count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group));
- ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon, group->Number).get_data();
- }
-
- return ret;
-}
-
-//Returns icon data by ID and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_icon_by_id(uint32_t id, uint32_t index) const
-{
- std::string ret;
-
- //Get resource by id and index
- const std::string data = res_.get_resource_data_by_id(pe_resource_viewer::resource_icon_group, id, index).get_data();
-
- //Create icon headers
- uint16_t icon_count = format_icon_headers(ret, data);
-
- //Append icon data
- for(uint16_t i = 0; i != icon_count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(data.data() + sizeof(ico_header) + i * sizeof(icon_group));
- ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_icon, group->Number, index).get_data();
- }
-
- return ret;
-}
-
-//Checks for icon presence inside icon group, fills icon headers if found
-bool resource_cursor_icon_reader::check_icon_presence(const std::string& icon_group_resource_data, uint32_t icon_id, std::string& ico_data)
-{
- //Check resource data size
- if(icon_group_resource_data.length() < sizeof(ico_header))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- //Get icon header
- const ico_header* info = reinterpret_cast<const ico_header*>(icon_group_resource_data.data());
-
- //Check resource data size
- if(icon_group_resource_data.length() < sizeof(ico_header) + info->Count * sizeof(icon_group))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- for(uint16_t i = 0; i != info->Count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(icon_group_resource_data.data() + sizeof(ico_header) + i * sizeof(icon_group));
- if(group->Number == icon_id)
- {
- //Reserve memory to speed up a little
- ico_data.reserve(sizeof(ico_header) + sizeof(icondirentry));
- //Write single-icon icon header
- ico_header new_header = *info;
- new_header.Count = 1;
- ico_data.append(reinterpret_cast<const char*>(&new_header), sizeof(ico_header));
-
- //Fill icon data
- icondirentry direntry;
- direntry.BitCount = group->BitCount;
- direntry.ColorCount = group->ColorCount;
- direntry.Height = group->Height;
- direntry.Planes = group->Planes;
- direntry.Reserved = group->Reserved;
- direntry.SizeInBytes = group->SizeInBytes;
- direntry.Width = group->Width;
- direntry.ImageOffset = sizeof(ico_header) + sizeof(icondirentry);
- ico_data.append(reinterpret_cast<const char*>(&direntry), sizeof(direntry));
-
- return true;
- }
- }
-
- return false;
-}
-
-//Looks up icon group by icon id and returns full icon headers if found
-const std::string resource_cursor_icon_reader::lookup_icon_group_data_by_icon(uint32_t icon_id, uint32_t language) const
-{
- std::string icon_header_data;
-
- {
- //List all ID-resources
- pe_resource_viewer::resource_id_list ids(res_.list_resource_ids(pe_resource_viewer::resource_icon_group));
-
- for(pe_resource_viewer::resource_id_list::const_iterator it = ids.begin(); it != ids.end(); ++it)
- {
- pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_icon_group, *it));
- if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end()
- && check_icon_presence(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, *it).get_data(), icon_id, icon_header_data))
- return icon_header_data;
- }
- }
-
- {
- //List all named resources
- pe_resource_viewer::resource_name_list names(res_.list_resource_names(pe_resource_viewer::resource_icon_group));
- for(pe_resource_viewer::resource_name_list::const_iterator it = names.begin(); it != names.end(); ++it)
- {
- pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_icon_group, *it));
- if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end()
- && check_icon_presence(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, *it).get_data(), icon_id, icon_header_data))
- return icon_header_data;
- }
- }
-
- throw pe_exception("No icon group find for requested icon", pe_exception::no_icon_group_found);
-}
-
-//Returns single cursor data by ID and language (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_single_cursor_by_id_lang(uint32_t language, uint32_t id) const
-{
- std::string raw_cursor_data(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, id).get_data());
- //Get cursor headers
- std::string cursor_data(lookup_cursor_group_data_by_cursor(id, language, raw_cursor_data));
- //Append cursor data
- cursor_data.append(raw_cursor_data.substr(sizeof(uint16_t) * 2 /* hotspot position */));
- return cursor_data;
-}
-
-//Returns single cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_single_cursor_by_id(uint32_t id, uint32_t index) const
-{
- pe_resource_viewer::resource_language_list languages(res_.list_resource_languages(pe_resource_viewer::resource_cursor, id));
- if(languages.size() <= index)
- throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found);
-
- std::string raw_cursor_data(res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, id, index).get_data());
- //Get cursor headers
- std::string cursor_data(lookup_cursor_group_data_by_cursor(id, languages.at(index), raw_cursor_data));
- //Append cursor data
- cursor_data.append(raw_cursor_data.substr(sizeof(uint16_t) * 2 /* hotspot position */));
- return cursor_data;
-}
-
-//Helper function of creating cursor headers
-//Returns cursor count
-uint16_t resource_cursor_icon_reader::format_cursor_headers(std::string& cur_data, const std::string& resource_data, uint32_t language, uint32_t index) const
-{
- //Check resource data length
- if(resource_data.length() < sizeof(cursor_header))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- const cursor_header* info = reinterpret_cast<const cursor_header*>(resource_data.data());
-
- //Check resource data length
- if(resource_data.length() < sizeof(cursor_header) + sizeof(cursor_group) * info->Count)
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Reserve needed space to speed up a little
- cur_data.reserve(sizeof(cursor_header) + info->Count * sizeof(cursordirentry));
- //Add cursor header
- cur_data.append(reinterpret_cast<const char*>(info), sizeof(cursor_header));
-
- //Iterate over all cursors listed in cursor group
- uint32_t offset = sizeof(cursor_header) + sizeof(cursordirentry) * info->Count;
- for(uint16_t i = 0; i != info->Count; ++i)
- {
- const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group));
-
- //Fill cursor info
- cursordirentry direntry;
- direntry.ColorCount = 0; //OK
- direntry.Width = static_cast<uint8_t>(group->Width);
- direntry.Height = static_cast<uint8_t>(group->Height) / 2;
- direntry.Reserved = 0;
-
- //Now read hotspot data from cursor data directory
- const std::string cursor = index == 0xFFFFFFFF
- ? res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, group->Number).get_data()
- : res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, group->Number, index).get_data();
- if(cursor.length() < 2 * sizeof(uint16_t))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Here it is - two words in the very beginning of cursor data
- direntry.HotspotX = *reinterpret_cast<const uint16_t*>(cursor.data());
- direntry.HotspotY = *reinterpret_cast<const uint16_t*>(cursor.data() + sizeof(uint16_t));
-
- //Fill the rest data
- direntry.SizeInBytes = group->SizeInBytes - 2 * sizeof(uint16_t);
- direntry.ImageOffset = offset;
-
- //Add cursor header
- cur_data.append(reinterpret_cast<const char*>(&direntry), sizeof(cursordirentry));
-
- offset += direntry.SizeInBytes;
- }
-
- //Return cursor count
- return info->Count;
-}
-
-//Returns cursor data by name and language (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_cursor_by_name(uint32_t language, const std::wstring& name) const
-{
- std::string ret;
-
- //Get resource by name and language
- const std::string resource_data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, name).get_data();
-
- //Create cursor headers
- uint16_t cursor_count = format_cursor_headers(ret, resource_data, language);
-
- //Add cursor data
- for(uint16_t i = 0; i != cursor_count; ++i)
- {
- const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group));
- ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, group->Number).get_data().substr(2 * sizeof(uint16_t));
- }
-
- return ret;
-}
-
-//Returns cursor data by name and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_cursor_by_name(const std::wstring& name, uint32_t index) const
-{
- std::string ret;
-
- //Get resource by name and index
- const std::string resource_data = res_.get_resource_data_by_name(pe_resource_viewer::resource_cursor_group, name, index).get_data();
-
- //Create cursor headers
- uint16_t cursor_count = format_cursor_headers(ret, resource_data, 0, index);
-
- //Add cursor data
- for(uint16_t i = 0; i != cursor_count; ++i)
- {
- const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group));
- ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, group->Number, index).get_data().substr(2 * sizeof(uint16_t));
- }
-
- return ret;
-}
-
-//Returns cursor data by ID and language (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_cursor_by_id_lang(uint32_t language, uint32_t id) const
-{
- std::string ret;
-
- //Get resource by ID and language
- const std::string resource_data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, id).get_data();
-
- //Create cursor headers
- uint16_t cursor_count = format_cursor_headers(ret, resource_data, language);
-
- //Add cursor data
- for(uint16_t i = 0; i != cursor_count; ++i)
- {
- const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group));
- ret += res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor, group->Number).get_data().substr(2 * sizeof(uint16_t));
- }
-
- return ret;
-}
-
-//Returns cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness)
-const std::string resource_cursor_icon_reader::get_cursor_by_id(uint32_t id, uint32_t index) const
-{
- std::string ret;
-
- //Get resource by ID and index
- const std::string resource_data = res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor_group, id, index).get_data();
-
- //Create cursor headers
- uint16_t cursor_count = format_cursor_headers(ret, resource_data, 0, index);
-
- //Add cursor data
- for(uint16_t i = 0; i != cursor_count; ++i)
- {
- const cursor_group* group = reinterpret_cast<const cursor_group*>(resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group));
- ret += res_.get_resource_data_by_id(pe_resource_viewer::resource_cursor, group->Number, index).get_data().substr(2 * sizeof(uint16_t));
- }
-
- return ret;
-}
-
-//Checks for cursor presence inside cursor group, fills cursor headers if found
-bool resource_cursor_icon_reader::check_cursor_presence(const std::string& cursor_group_resource_data, uint32_t cursor_id, std::string& cur_header_data, const std::string& raw_cursor_data)
-{
- //Check resource data length
- if(cursor_group_resource_data.length() < sizeof(cursor_header))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- const cursor_header* info = reinterpret_cast<const cursor_header*>(cursor_group_resource_data.data());
-
- //Check resource data length
- if(cursor_group_resource_data.length() < sizeof(cursor_header) + sizeof(cursor_group))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Iterate over all cursors listed in cursor group
- for(uint16_t i = 0; i != info->Count; ++i)
- {
- const cursor_group* group = reinterpret_cast<const cursor_group*>(cursor_group_resource_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group));
-
- if(group->Number == cursor_id)
- {
- //Reserve needed space to speed up a little
- cur_header_data.reserve(sizeof(cursor_header) + sizeof(cursordirentry));
- //Write single-cursor cursor header
- cursor_header new_header = *info;
- new_header.Count = 1;
- cur_header_data.append(reinterpret_cast<const char*>(&new_header), sizeof(cursor_header));
-
- //Fill cursor info
- cursordirentry direntry;
- direntry.ColorCount = 0; //OK
- direntry.Width = static_cast<uint8_t>(group->Width);
- direntry.Height = static_cast<uint8_t>(group->Height) / 2;
- direntry.Reserved = 0;
-
- if(raw_cursor_data.length() < 2 * sizeof(uint16_t))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Here it is - two words in the very beginning of cursor data
- direntry.HotspotX = *reinterpret_cast<const uint16_t*>(raw_cursor_data.data());
- direntry.HotspotY = *reinterpret_cast<const uint16_t*>(raw_cursor_data.data() + sizeof(uint16_t));
-
- //Fill the rest data
- direntry.SizeInBytes = group->SizeInBytes - 2 * sizeof(uint16_t);
- direntry.ImageOffset = sizeof(cursor_header) + sizeof(cursordirentry);
-
- //Add cursor header
- cur_header_data.append(reinterpret_cast<const char*>(&direntry), sizeof(cursordirentry));
-
- return true;
- }
- }
-
- return false;
-}
-
-//Looks up cursor group by cursor id and returns full cursor headers if found
-const std::string resource_cursor_icon_reader::lookup_cursor_group_data_by_cursor(uint32_t cursor_id, uint32_t language, const std::string& raw_cursor_data) const
-{
- std::string cursor_header_data;
-
- {
- //List all ID-resources
- pe_resource_viewer::resource_id_list ids(res_.list_resource_ids(pe_resource_viewer::resource_cursor_group));
-
- for(pe_resource_viewer::resource_id_list::const_iterator it = ids.begin(); it != ids.end(); ++it)
- {
- pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_cursor_group, *it));
- if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end()
- && check_cursor_presence(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, *it).get_data(), cursor_id, cursor_header_data, raw_cursor_data))
- return cursor_header_data;
- }
- }
-
- {
- //List all named resources
- pe_resource_viewer::resource_name_list names(res_.list_resource_names(pe_resource_viewer::resource_cursor_group));
- for(pe_resource_viewer::resource_name_list::const_iterator it = names.begin(); it != names.end(); ++it)
- {
- pe_resource_viewer::resource_language_list group_languages(res_.list_resource_languages(pe_resource_viewer::resource_cursor_group, *it));
- if(std::find(group_languages.begin(), group_languages.end(), language) != group_languages.end()
- && check_cursor_presence(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, *it).get_data(), cursor_id, cursor_header_data, raw_cursor_data))
- return cursor_header_data;
- }
- }
-
- throw pe_exception("No cursor group find for requested icon", pe_exception::no_cursor_group_found);
-}
-}
diff --git a/tools/pe_bliss/resource_cursor_icon_reader.h b/tools/pe_bliss/resource_cursor_icon_reader.h
deleted file mode 100644
index e34fff419b..0000000000
--- a/tools/pe_bliss/resource_cursor_icon_reader.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-class pe_resource_viewer;
-
-class resource_cursor_icon_reader
-{
-public:
- resource_cursor_icon_reader(const pe_resource_viewer& res);
-
- //Returns single icon data by ID and language (minimum checks of format correctness)
- const std::string get_single_icon_by_id_lang(uint32_t language, uint32_t id) const;
- //Returns single icon data by ID and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_single_icon_by_id(uint32_t id, uint32_t index = 0) const;
-
- //Returns icon data of group of icons by name and language (minimum checks of format correctness)
- const std::string get_icon_by_name(uint32_t language, const std::wstring& icon_group_name) const;
- //Returns icon data of group of icons by name and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_icon_by_name(const std::wstring& icon_group_name, uint32_t index = 0) const;
- //Returns icon data of group of icons by ID and language (minimum checks of format correctness)
- const std::string get_icon_by_id_lang(uint32_t language, uint32_t icon_group_id) const;
- //Returns icon data of group of icons by ID and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_icon_by_id(uint32_t icon_group_id, uint32_t index = 0) const;
-
- //Returns single cursor data by ID and language (minimum checks of format correctness)
- const std::string get_single_cursor_by_id_lang(uint32_t language, uint32_t id) const;
- //Returns single cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_single_cursor_by_id(uint32_t id, uint32_t index = 0) const;
-
- //Returns cursor data by name and language (minimum checks of format correctness)
- const std::string get_cursor_by_name(uint32_t language, const std::wstring& cursor_group_name) const;
- //Returns cursor data by name and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_cursor_by_name(const std::wstring& cursor_group_name, uint32_t index = 0) const;
- //Returns cursor data by ID and language (minimum checks of format correctness)
- const std::string get_cursor_by_id_lang(uint32_t language, uint32_t cursor_group_id) const;
- //Returns cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness)
- const std::string get_cursor_by_id(uint32_t cursor_group_id, uint32_t index = 0) const;
-
-private:
- const pe_resource_viewer& res_;
-
- //Helper function of creating icon headers from ICON_GROUP resource data
- //Returns icon count
- static uint16_t format_icon_headers(std::string& ico_data, const std::string& resource_data);
-
- //Helper function of creating cursor headers from CURSOR_GROUP resource data
- //Returns cursor count
- uint16_t format_cursor_headers(std::string& cur_data, const std::string& resource_data, uint32_t language, uint32_t index = 0xFFFFFFFF) const;
-
- //Looks up icon group by icon id and returns full icon headers if found
- const std::string lookup_icon_group_data_by_icon(uint32_t icon_id, uint32_t language) const;
- //Checks for icon presence inside icon group, fills icon headers if found
- static bool check_icon_presence(const std::string& icon_group_resource_data, uint32_t icon_id, std::string& ico_data);
-
- //Looks up cursor group by cursor id and returns full cursor headers if found
- const std::string lookup_cursor_group_data_by_cursor(uint32_t cursor_id, uint32_t language, const std::string& raw_cursor_data) const;
- //Checks for cursor presence inside cursor group, fills cursor headers if found
- static bool check_cursor_presence(const std::string& icon_group_resource_data, uint32_t cursor_id, std::string& cur_header_data, const std::string& raw_cursor_data);
-};
-}
diff --git a/tools/pe_bliss/resource_cursor_icon_writer.cpp b/tools/pe_bliss/resource_cursor_icon_writer.cpp
deleted file mode 100644
index 2f1c4363c4..0000000000
--- a/tools/pe_bliss/resource_cursor_icon_writer.cpp
+++ /dev/null
@@ -1,447 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <algorithm>
-#include <string.h>
-#include "resource_cursor_icon_writer.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-resource_cursor_icon_writer::resource_cursor_icon_writer(pe_resource_manager& res)
- :res_(res)
-{}
-
-//Add icon helper
-void resource_cursor_icon_writer::add_icon(const std::string& icon_file, const resource_data_info* group_icon_info /* or zero */, resource_directory_entry& new_icon_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp)
-{
- //Check icon for correctness
- if(icon_file.length() < sizeof(ico_header))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- const ico_header* icon_header = reinterpret_cast<const ico_header*>(&icon_file[0]);
-
- unsigned long size_of_headers = sizeof(ico_header) + icon_header->Count * sizeof(icondirentry);
- if(icon_file.length() < size_of_headers || icon_header->Count == 0)
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- //Enumerate all icons in file
- for(uint16_t i = 0; i != icon_header->Count; ++i)
- {
- //Check icon entries
- const icondirentry* icon_entry = reinterpret_cast<const icondirentry*>(&icon_file[sizeof(ico_header) + i * sizeof(icondirentry)]);
- if(icon_entry->SizeInBytes == 0
- || icon_entry->ImageOffset < size_of_headers
- || !pe_utils::is_sum_safe(icon_entry->ImageOffset, icon_entry->SizeInBytes)
- || icon_entry->ImageOffset + icon_entry->SizeInBytes > icon_file.length())
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
- }
-
- std::string icon_group_data;
- ico_header* info = 0;
-
- if(group_icon_info)
- {
- //If icon group already exists
- {
- icon_group_data = group_icon_info->get_data();
- codepage = group_icon_info->get_codepage(); //Don't change codepage of icon group entry
- }
-
- //Check resource data size
- if(icon_group_data.length() < sizeof(ico_header))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- //Get icon header
- info = reinterpret_cast<ico_header*>(&icon_group_data[0]);
-
- //Check resource data size
- if(icon_group_data.length() < sizeof(ico_header) + info->Count * sizeof(icon_group))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- icon_group_data.resize(sizeof(ico_header) + (info->Count + icon_header->Count) * sizeof(icon_group));
- info = reinterpret_cast<ico_header*>(&icon_group_data[0]); //In case if memory was reallocated
- }
- else //Entry not found - icon group doesn't exist
- {
- icon_group_data.resize(sizeof(ico_header) + icon_header->Count * sizeof(icon_group));
- memcpy(&icon_group_data[0], icon_header, sizeof(ico_header));
- }
-
- //Search for available icon IDs
- std::vector<uint16_t> icon_id_list(get_icon_or_cursor_free_id_list(pe_resource_viewer::resource_icon, mode, icon_header->Count));
-
- //Enumerate all icons in file
- for(uint16_t i = 0; i != icon_header->Count; ++i)
- {
- const icondirentry* icon_entry = reinterpret_cast<const icondirentry*>(&icon_file[sizeof(ico_header) + i * sizeof(icondirentry)]);
- icon_group group = {0};
-
- //Fill icon resource header
- group.BitCount = icon_entry->BitCount;
- group.ColorCount = icon_entry->ColorCount;
- group.Height = icon_entry->Height;
- group.Planes = icon_entry->Planes;
- group.Reserved = icon_entry->Reserved;
- group.SizeInBytes = icon_entry->SizeInBytes;
- group.Width = icon_entry->Width;
- group.Number = icon_id_list.at(i);
-
- memcpy(&icon_group_data[sizeof(ico_header) + ((info ? info->Count : 0) + i) * sizeof(icon_group)], &group, sizeof(group));
-
- //Add icon to resources
- resource_directory_entry new_entry;
- new_entry.set_id(group.Number);
- res_.add_resource(icon_file.substr(icon_entry->ImageOffset, icon_entry->SizeInBytes), pe_resource_viewer::resource_icon, new_entry, resource_directory::entry_finder(group.Number), language, codepage, timestamp);
- }
-
- if(info)
- info->Count += icon_header->Count; //Increase icon count, if we're adding icon to existing group
-
- {
- //Add or replace icon group data entry
- res_.add_resource(icon_group_data, pe_resource_viewer::resource_icon_group, new_icon_group_entry, finder, language, codepage, timestamp);
- }
-}
-
-//Returns free icon or cursor ID list depending on icon_place_mode
-const std::vector<uint16_t> resource_cursor_icon_writer::get_icon_or_cursor_free_id_list(pe_resource_viewer::resource_type type, icon_place_mode mode, uint32_t count)
-{
- //Search for available icon/cursor IDs
- std::vector<uint16_t> icon_cursor_id_list;
-
- try
- {
- //If any icon exists
- //List icon IDs
- std::vector<uint32_t> id_list(res_.list_resource_ids(type));
- std::sort(id_list.begin(), id_list.end());
-
- //If we are placing icon on free spaces
- //I.e., icon IDs 1, 3, 4, 7, 8 already exist
- //We'll place five icons on IDs 2, 5, 6, 9, 10
- if(mode != icon_place_after_max_icon_id)
- {
- if(!id_list.empty())
- {
- //Determine and list free icon IDs
- for(std::vector<uint32_t>::const_iterator it = id_list.begin(); it != id_list.end(); ++it)
- {
- if(it == id_list.begin())
- {
- if(*it > 1)
- {
- for(uint16_t i = 1; i != *it; ++i)
- {
- icon_cursor_id_list.push_back(i);
- if(icon_cursor_id_list.size() == count)
- break;
- }
- }
- }
- else if(*(it - 1) - *it > 1)
- {
- for(uint16_t i = static_cast<uint16_t>(*(it - 1) + 1); i != static_cast<uint16_t>(*it); ++i)
- {
- icon_cursor_id_list.push_back(i);
- if(icon_cursor_id_list.size() == count)
- break;
- }
- }
-
- if(icon_cursor_id_list.size() == count)
- break;
- }
- }
- }
-
- uint32_t max_id = id_list.empty() ? 0 : *std::max_element(id_list.begin(), id_list.end());
- for(uint32_t i = static_cast<uint32_t>(icon_cursor_id_list.size()); i != count; ++i)
- icon_cursor_id_list.push_back(static_cast<uint16_t>(++max_id));
- }
- catch(const pe_exception&) //Entry not found
- {
- for(uint16_t i = 1; i != count + 1; ++i)
- icon_cursor_id_list.push_back(i);
- }
-
- return icon_cursor_id_list;
-}
-
-//Add cursor helper
-void resource_cursor_icon_writer::add_cursor(const std::string& cursor_file, const resource_data_info* group_cursor_info /* or zero */, resource_directory_entry& new_cursor_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp)
-{
- //Check cursor for correctness
- if(cursor_file.length() < sizeof(cursor_header))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- const cursor_header* cur_header = reinterpret_cast<const cursor_header*>(&cursor_file[0]);
-
- unsigned long size_of_headers = sizeof(cursor_header) + cur_header->Count * sizeof(cursordirentry);
- if(cursor_file.length() < size_of_headers || cur_header->Count == 0)
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Enumerate all cursors in file
- for(uint16_t i = 0; i != cur_header->Count; ++i)
- {
- //Check cursor entries
- const cursordirentry* cursor_entry = reinterpret_cast<const cursordirentry*>(&cursor_file[sizeof(cursor_header) + i * sizeof(cursordirentry)]);
- if(cursor_entry->SizeInBytes == 0
- || cursor_entry->ImageOffset < size_of_headers
- || !pe_utils::is_sum_safe(cursor_entry->ImageOffset, cursor_entry->SizeInBytes)
- || cursor_entry->ImageOffset + cursor_entry->SizeInBytes > cursor_file.length())
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
- }
-
- std::string cursor_group_data;
- cursor_header* info = 0;
-
- if(group_cursor_info)
- {
- //If cursor group already exists
- {
- cursor_group_data = group_cursor_info->get_data();
- codepage = group_cursor_info->get_codepage(); //Don't change codepage of cursor group entry
- }
-
- //Check resource data size
- if(cursor_group_data.length() < sizeof(cursor_header))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Get cursor header
- info = reinterpret_cast<cursor_header*>(&cursor_group_data[0]);
-
- //Check resource data size
- if(cursor_group_data.length() < sizeof(cursor_header) + info->Count * sizeof(cursor_group))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- cursor_group_data.resize(sizeof(cursor_header) + (info->Count + cur_header->Count) * sizeof(cursor_group));
- info = reinterpret_cast<cursor_header*>(&cursor_group_data[0]); //In case if memory was reallocated
- }
- else //Entry not found - cursor group doesn't exist
- {
- cursor_group_data.resize(sizeof(cursor_header) + cur_header->Count * sizeof(cursor_group));
- memcpy(&cursor_group_data[0], cur_header, sizeof(cursor_header));
- }
-
- //Search for available cursor IDs
- std::vector<uint16_t> cursor_id_list(get_icon_or_cursor_free_id_list(pe_resource_viewer::resource_cursor, mode, cur_header->Count));
-
- //Enumerate all cursors in file
- for(uint16_t i = 0; i != cur_header->Count; ++i)
- {
- const cursordirentry* cursor_entry = reinterpret_cast<const cursordirentry*>(&cursor_file[sizeof(cursor_header) + i * sizeof(cursordirentry)]);
- cursor_group group = {0};
-
- //Fill cursor resource header
- group.Height = cursor_entry->Height * 2;
- group.SizeInBytes = cursor_entry->SizeInBytes + 2 * sizeof(uint16_t) /* hotspot coordinates */;
- group.Width = cursor_entry->Width;
- group.Number = cursor_id_list.at(i);
-
- memcpy(&cursor_group_data[sizeof(cursor_header) + ((info ? info->Count : 0) + i) * sizeof(cursor_group)], &group, sizeof(group));
-
- //Add cursor to resources
- resource_directory_entry new_entry;
- new_entry.set_id(group.Number);
-
- //Fill resource data (two WORDs for hotspot of cursor, and cursor bitmap data)
- std::string cur_data;
- cur_data.resize(sizeof(uint16_t) * 2);
- memcpy(&cur_data[0], &cursor_entry->HotspotX, sizeof(uint16_t));
- memcpy(&cur_data[sizeof(uint16_t)], &cursor_entry->HotspotY, sizeof(uint16_t));
- cur_data.append(cursor_file.substr(cursor_entry->ImageOffset, cursor_entry->SizeInBytes));
-
- res_.add_resource(cur_data, pe_resource_viewer::resource_cursor, new_entry, resource_directory::entry_finder(group.Number), language, codepage, timestamp);
- }
-
- if(info)
- info->Count += cur_header->Count; //Increase cursor count, if we're adding cursor to existing group
-
- {
- //Add or replace cursor group data entry
- res_.add_resource(cursor_group_data, pe_resource_viewer::resource_cursor_group, new_cursor_group_entry, finder, language, codepage, timestamp);
- }
-}
-
-//Adds icon(s) from icon file data
-//timestamp will be used for directories that will be added
-//If icon group with name "icon_group_name" or ID "icon_group_id" already exists, it will be appended with new icon(s)
-//(Codepage of icon group and icons will not be changed in this case)
-//icon_place_mode determines, how new icon(s) will be placed
-void resource_cursor_icon_writer::add_icon(const std::string& icon_file, const std::wstring& icon_group_name, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_icon_group_entry;
- new_icon_group_entry.set_name(icon_group_name);
- std::auto_ptr<resource_data_info> data_info;
-
- try
- {
- data_info.reset(new resource_data_info(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, icon_group_name)));
- }
- catch(const pe_exception&) //Entry not found
- {
- }
-
- add_icon(icon_file, data_info.get(), new_icon_group_entry, resource_directory::entry_finder(icon_group_name), language, mode, codepage, timestamp);
-}
-
-void resource_cursor_icon_writer::add_icon(const std::string& icon_file, uint32_t icon_group_id, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_icon_group_entry;
- new_icon_group_entry.set_id(icon_group_id);
- std::auto_ptr<resource_data_info> data_info;
-
- try
- {
- data_info.reset(new resource_data_info(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, icon_group_id)));
- }
- catch(const pe_exception&) //Entry not found
- {
- }
-
- add_icon(icon_file, data_info.get(), new_icon_group_entry, resource_directory::entry_finder(icon_group_id), language, mode, codepage, timestamp);
-}
-
-//Adds cursor(s) from cursor file data
-//timestamp will be used for directories that will be added
-//If cursor group with name "cursor_group_name" or ID "cursor_group_id" already exists, it will be appended with new cursor(s)
-//(Codepage of cursor group and cursors will not be changed in this case)
-//icon_place_mode determines, how new cursor(s) will be placed
-void resource_cursor_icon_writer::add_cursor(const std::string& cursor_file, const std::wstring& cursor_group_name, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_cursor_group_entry;
- new_cursor_group_entry.set_name(cursor_group_name);
- std::auto_ptr<resource_data_info> data_info;
-
- try
- {
- data_info.reset(new resource_data_info(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, cursor_group_name)));
- }
- catch(const pe_exception&) //Entry not found
- {
- }
-
- add_cursor(cursor_file, data_info.get(), new_cursor_group_entry, resource_directory::entry_finder(cursor_group_name), language, mode, codepage, timestamp);
-}
-
-void resource_cursor_icon_writer::add_cursor(const std::string& cursor_file, uint32_t cursor_group_id, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp)
-{
- resource_directory_entry new_cursor_group_entry;
- new_cursor_group_entry.set_id(cursor_group_id);
- std::auto_ptr<resource_data_info> data_info;
-
- try
- {
- data_info.reset(new resource_data_info(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, cursor_group_id)));
- }
- catch(const pe_exception&) //Entry not found
- {
- }
-
- add_cursor(cursor_file, data_info.get(), new_cursor_group_entry, resource_directory::entry_finder(cursor_group_id), language, mode, codepage, timestamp);
-}
-
-//Remove icon group helper
-void resource_cursor_icon_writer::remove_icons_from_icon_group(const std::string& icon_group_data, uint32_t language)
-{
- //Check resource data size
- if(icon_group_data.length() < sizeof(ico_header))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- //Get icon header
- const ico_header* info = reinterpret_cast<const ico_header*>(icon_group_data.data());
-
- uint16_t icon_count = info->Count;
-
- //Check resource data size
- if(icon_group_data.length() < sizeof(ico_header) + icon_count * sizeof(icon_group))
- throw pe_exception("Incorrect resource icon", pe_exception::resource_incorrect_icon);
-
- //Remove icon data
- for(uint16_t i = 0; i != icon_count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(icon_group_data.data() + sizeof(ico_header) + i * sizeof(icon_group));
- res_.remove_resource(pe_resource_viewer::resource_icon, group->Number, language);
- }
-}
-
-//Remove cursor group helper
-void resource_cursor_icon_writer::remove_cursors_from_cursor_group(const std::string& cursor_group_data, uint32_t language)
-{
- //Check resource data size
- if(cursor_group_data.length() < sizeof(cursor_header))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Get icon header
- const cursor_header* info = reinterpret_cast<const cursor_header*>(cursor_group_data.data());
-
- uint16_t cursor_count = info->Count;
-
- //Check resource data size
- if(cursor_group_data.length() < sizeof(cursor_header) + cursor_count * sizeof(cursor_group))
- throw pe_exception("Incorrect resource cursor", pe_exception::resource_incorrect_cursor);
-
- //Remove icon data
- for(uint16_t i = 0; i != cursor_count; ++i)
- {
- const icon_group* group = reinterpret_cast<const icon_group*>(cursor_group_data.data() + sizeof(cursor_header) + i * sizeof(cursor_group));
- res_.remove_resource(pe_resource_viewer::resource_cursor, group->Number, language);
- }
-}
-
-//Removes cursor group and all its cursors by name/ID and language
-bool resource_cursor_icon_writer::remove_cursor_group(const std::wstring& cursor_group_name, uint32_t language)
-{
- //Get resource by name and language
- const std::string data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_cursor_group, cursor_group_name).get_data();
- remove_cursors_from_cursor_group(data, language);
- return res_.remove_resource(pe_resource_viewer::resource_cursor_group, cursor_group_name, language);
-}
-
-//Removes cursor group and all its cursors by name/ID and language
-bool resource_cursor_icon_writer::remove_cursor_group(uint32_t cursor_group_id, uint32_t language)
-{
- //Get resource by name and language
- const std::string data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_cursor_group, cursor_group_id).get_data();
- remove_cursors_from_cursor_group(data, language);
- return res_.remove_resource(pe_resource_viewer::resource_cursor_group, cursor_group_id, language);
-}
-
-//Removes icon group and all its icons by name/ID and language
-bool resource_cursor_icon_writer::remove_icon_group(const std::wstring& icon_group_name, uint32_t language)
-{
- //Get resource by name and language
- const std::string data = res_.get_resource_data_by_name(language, pe_resource_viewer::resource_icon_group, icon_group_name).get_data();
- remove_icons_from_icon_group(data, language);
- return res_.remove_resource(pe_resource_viewer::resource_icon_group, icon_group_name, language);
-}
-
-//Removes icon group and all its icons by name/ID and language
-bool resource_cursor_icon_writer::remove_icon_group(uint32_t icon_group_id, uint32_t language)
-{
- //Get resource by name and language
- const std::string data = res_.get_resource_data_by_id(language, pe_resource_viewer::resource_icon_group, icon_group_id).get_data();
- remove_icons_from_icon_group(data, language);
- return res_.remove_resource(pe_resource_viewer::resource_icon_group, icon_group_id, language);
-}
-}
diff --git a/tools/pe_bliss/resource_cursor_icon_writer.h b/tools/pe_bliss/resource_cursor_icon_writer.h
deleted file mode 100644
index e73ac6a093..0000000000
--- a/tools/pe_bliss/resource_cursor_icon_writer.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include <vector>
-#include "stdint_defs.h"
-#include "pe_resource_manager.h"
-
-namespace pe_bliss
-{
-class pe_resource_manager;
-
-class resource_cursor_icon_writer
-{
-public:
- //Determines, how new icon(s) or cursor(s) will be placed
- enum icon_place_mode
- {
- icon_place_after_max_icon_id, //Icon(s) will be placed after all existing
- icon_place_free_ids //New icon(s) will take all free IDs between existing icons
- };
-
-public:
- resource_cursor_icon_writer(pe_resource_manager& res);
-
- //Removes icon group and all its icons by name/ID and language
- bool remove_icon_group(const std::wstring& icon_group_name, uint32_t language);
- bool remove_icon_group(uint32_t icon_group_id, uint32_t language);
-
- //Adds icon(s) from icon file data
- //timestamp will be used for directories that will be added
- //If icon group with name "icon_group_name" or ID "icon_group_id" already exists, it will be appended with new icon(s)
- //(Codepage of icon group and icons will not be changed in this case)
- //icon_place_mode determines, how new icon(s) will be placed
- void add_icon(const std::string& icon_file,
- const std::wstring& icon_group_name,
- uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id,
- uint32_t codepage = 0, uint32_t timestamp = 0);
-
- void add_icon(const std::string& icon_file,
- uint32_t icon_group_id,
- uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id,
- uint32_t codepage = 0, uint32_t timestamp = 0);
-
- //Removes cursor group and all its cursors by name/ID and language
- bool remove_cursor_group(const std::wstring& cursor_group_name, uint32_t language);
- bool remove_cursor_group(uint32_t cursor_group_id, uint32_t language);
-
- //Adds cursor(s) from cursor file data
- //timestamp will be used for directories that will be added
- //If cursor group with name "cursor_group_name" or ID "cursor_group_id" already exists, it will be appended with new cursor(s)
- //(Codepage of cursor group and cursors will not be changed in this case)
- //icon_place_mode determines, how new cursor(s) will be placed
- void add_cursor(const std::string& cursor_file, const std::wstring& cursor_group_name, uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, uint32_t codepage = 0, uint32_t timestamp = 0);
- void add_cursor(const std::string& cursor_file, uint32_t cursor_group_id, uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, uint32_t codepage = 0, uint32_t timestamp = 0);
-
-private:
- pe_resource_manager& res_;
-
- //Add icon helper
- void add_icon(const std::string& icon_file, const resource_data_info* group_icon_info /* or zero */, resource_directory_entry& new_icon_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp);
-
- //Remove icon group helper
- void remove_icons_from_icon_group(const std::string& icon_group_data, uint32_t language);
-
- //Add cursor helper
- void add_cursor(const std::string& cursor_file, const resource_data_info* group_cursor_info /* or zero */, resource_directory_entry& new_cursor_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp);
-
- //Remove cursor group helper
- void remove_cursors_from_cursor_group(const std::string& cursor_group_data, uint32_t language);
-
- //Returns free icon or cursor ID list depending on icon_place_mode
- const std::vector<uint16_t> get_icon_or_cursor_free_id_list(pe_resource_manager::resource_type type, icon_place_mode mode, uint32_t count);
-};
-}
diff --git a/tools/pe_bliss/resource_data_info.cpp b/tools/pe_bliss/resource_data_info.cpp
deleted file mode 100644
index 75bb060eae..0000000000
--- a/tools/pe_bliss/resource_data_info.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "resource_data_info.h"
-#include "pe_resource_viewer.h"
-
-namespace pe_bliss
-{
-//Default constructor
-resource_data_info::resource_data_info(const std::string& data, uint32_t codepage)
- :data_(data), codepage_(codepage)
-{}
-
-//Constructor from data
-resource_data_info::resource_data_info(const resource_data_entry& data)
- :data_(data.get_data()), codepage_(data.get_codepage())
-{}
-
-//Returns resource data
-const std::string& resource_data_info::get_data() const
-{
- return data_;
-}
-
-//Returns resource codepage
-uint32_t resource_data_info::get_codepage() const
-{
- return codepage_;
-}
-}
diff --git a/tools/pe_bliss/resource_data_info.h b/tools/pe_bliss/resource_data_info.h
deleted file mode 100644
index e2275ebbf5..0000000000
--- a/tools/pe_bliss/resource_data_info.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-class resource_data_entry;
-
-//Class representing resource data
-class resource_data_info
-{
-public:
- //Constructor from data
- resource_data_info(const std::string& data, uint32_t codepage);
- //Constructor from data
- explicit resource_data_info(const resource_data_entry& data);
-
- //Returns resource data
- const std::string& get_data() const;
- //Returns resource codepage
- uint32_t get_codepage() const;
-
-private:
- std::string data_;
- uint32_t codepage_;
-};
-}
diff --git a/tools/pe_bliss/resource_internal.h b/tools/pe_bliss/resource_internal.h
deleted file mode 100644
index 64a5bf3903..0000000000
--- a/tools/pe_bliss/resource_internal.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-
-#define U16TEXT(t) reinterpret_cast<const unicode16_t*>( t )
-
-#define StringFileInfo U16TEXT("S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0")
-#define SizeofStringFileInfo sizeof("S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0")
-#define VarFileInfo U16TEXT("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0")
-#define Translation U16TEXT("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0")
-
-#define VarFileInfoAligned U16TEXT("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0\0")
-#define TranslationAligned U16TEXT("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0\0\0")
-#define SizeofVarFileInfoAligned sizeof("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0\0")
-#define SizeofTranslationAligned sizeof("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0\0\0")
diff --git a/tools/pe_bliss/resource_message_list_reader.cpp b/tools/pe_bliss/resource_message_list_reader.cpp
deleted file mode 100644
index f2ea142bee..0000000000
--- a/tools/pe_bliss/resource_message_list_reader.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "resource_message_list_reader.h"
-#include "pe_resource_viewer.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-resource_message_list_reader::resource_message_list_reader(const pe_resource_viewer& res)
- :res_(res)
-{}
-
-//Helper function of parsing message list table
-const resource_message_list resource_message_list_reader::parse_message_list(const std::string& resource_data)
-{
- resource_message_list ret;
-
- //Check resource data length
- if(resource_data.length() < sizeof(message_resource_data))
- throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table);
-
- const message_resource_data* message_data = reinterpret_cast<const message_resource_data*>(resource_data.data());
-
- //Check resource data length more carefully and some possible overflows
- if(message_data->NumberOfBlocks >= pe_utils::max_dword / sizeof(message_resource_block)
- || !pe_utils::is_sum_safe(message_data->NumberOfBlocks * sizeof(message_resource_block), sizeof(message_resource_data))
- || resource_data.length() < message_data->NumberOfBlocks * sizeof(message_resource_block) + sizeof(message_resource_data))
- throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table);
-
- //Iterate over all message resource blocks
- for(unsigned long i = 0; i != message_data->NumberOfBlocks; ++i)
- {
- //Get block
- const message_resource_block* block =
- reinterpret_cast<const message_resource_block*>(resource_data.data() + sizeof(message_resource_data) - sizeof(message_resource_block) + sizeof(message_resource_block) * i);
-
- //Check resource data length and IDs
- if(resource_data.length() < block->OffsetToEntries || block->LowId > block->HighId)
- throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table);
-
- unsigned long current_pos = 0;
- static const unsigned long size_of_entry_headers = 4;
- //List all message resource entries in block
- for(uint32_t curr_id = block->LowId; curr_id <= block->HighId; curr_id++)
- {
- //Check resource data length and some possible overflows
- if(!pe_utils::is_sum_safe(block->OffsetToEntries, current_pos)
- || !pe_utils::is_sum_safe(block->OffsetToEntries + current_pos, size_of_entry_headers)
- || resource_data.length() < block->OffsetToEntries + current_pos + size_of_entry_headers)
- throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table);
-
- //Get entry
- const message_resource_entry* entry = reinterpret_cast<const message_resource_entry*>(resource_data.data() + block->OffsetToEntries + current_pos);
-
- //Check resource data length and entry length and some possible overflows
- if(entry->Length < size_of_entry_headers
- || !pe_utils::is_sum_safe(block->OffsetToEntries + current_pos, entry->Length)
- || resource_data.length() < block->OffsetToEntries + current_pos + entry->Length
- || entry->Length < size_of_entry_headers)
- throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table);
-
- if(entry->Flags & message_resource_unicode)
- {
- //If string is UNICODE
- //Check its length
- if(entry->Length % 2)
- throw pe_exception("Incorrect resource message table", pe_exception::resource_incorrect_message_table);
-
- //Add ID and string to message table
-#ifdef PE_BLISS_WINDOWS
- ret.insert(std::make_pair(curr_id, message_table_item(
- std::wstring(reinterpret_cast<const wchar_t*>(resource_data.data() + block->OffsetToEntries + current_pos + size_of_entry_headers),
- (entry->Length - size_of_entry_headers) / 2)
- )));
-#else
- ret.insert(std::make_pair(curr_id, message_table_item(
- pe_utils::from_ucs2(u16string(reinterpret_cast<const unicode16_t*>(resource_data.data() + block->OffsetToEntries + current_pos + size_of_entry_headers),
- (entry->Length - size_of_entry_headers) / 2))
- )));
-#endif
- }
- else
- {
- //If string is ANSI
- //Add ID and string to message table
- ret.insert(std::make_pair(curr_id, message_table_item(
- std::string(resource_data.data() + block->OffsetToEntries + current_pos + size_of_entry_headers,
- entry->Length - size_of_entry_headers)
- )));
- }
-
- //Go to next entry
- current_pos += entry->Length;
- }
- }
-
- return ret;
-}
-
-//Returns message table data by ID and index in language directory (instead of language)
-const resource_message_list resource_message_list_reader::get_message_table_by_id(uint32_t id, uint32_t index) const
-{
- return parse_message_list(res_.get_resource_data_by_id(pe_resource_viewer::resource_message_table, id, index).get_data());
-}
-
-//Returns message table data by ID and language
-const resource_message_list resource_message_list_reader::get_message_table_by_id_lang(uint32_t language, uint32_t id) const
-{
- return parse_message_list(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_message_table, id).get_data());
-}
-}
diff --git a/tools/pe_bliss/resource_message_list_reader.h b/tools/pe_bliss/resource_message_list_reader.h
deleted file mode 100644
index a0ac96eb8c..0000000000
--- a/tools/pe_bliss/resource_message_list_reader.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include "message_table.h"
-
-namespace pe_bliss
-{
-class pe_resource_viewer;
-
-//ID; message_table_item
-typedef std::map<uint32_t, message_table_item> resource_message_list;
-
-class resource_message_list_reader
-{
-public:
- resource_message_list_reader(const pe_resource_viewer& res);
-
- //Returns message table data by ID and language
- const resource_message_list get_message_table_by_id_lang(uint32_t language, uint32_t id) const;
- //Returns message table data by ID and index in language directory (instead of language)
- const resource_message_list get_message_table_by_id(uint32_t id, uint32_t index = 0) const;
-
- //Helper function of parsing message list table
- //resource_data - raw message table resource data
- static const resource_message_list parse_message_list(const std::string& resource_data);
-
-private:
- const pe_resource_viewer& res_;
-};
-}
diff --git a/tools/pe_bliss/resource_string_table_reader.cpp b/tools/pe_bliss/resource_string_table_reader.cpp
deleted file mode 100644
index 8a51720e6a..0000000000
--- a/tools/pe_bliss/resource_string_table_reader.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "resource_string_table_reader.h"
-#include "pe_resource_viewer.h"
-
-namespace pe_bliss
-{
-resource_string_table_reader::resource_string_table_reader(const pe_resource_viewer& res)
- :res_(res)
-{}
-
-//Returns string table data by ID and index in language directory (instead of language)
-const resource_string_list resource_string_table_reader::get_string_table_by_id(uint32_t id, uint32_t index) const
-{
- return parse_string_list(id, res_.get_resource_data_by_id(pe_resource_viewer::resource_string, id, index).get_data());
-}
-
-//Returns string table data by ID and language
-const resource_string_list resource_string_table_reader::get_string_table_by_id_lang(uint32_t language, uint32_t id) const
-{
- return parse_string_list(id, res_.get_resource_data_by_id(language, pe_resource_viewer::resource_string, id).get_data());
-}
-
-//Helper function of parsing string list table
-const resource_string_list resource_string_table_reader::parse_string_list(uint32_t id, const std::string& resource_data)
-{
- resource_string_list ret;
-
- //16 is maximum count of strings in a string table
- static const unsigned long max_string_list_entries = 16;
- unsigned long passed_bytes = 0;
- for(unsigned long i = 0; i != max_string_list_entries; ++i)
- {
- //Check resource data length
- if(resource_data.length() < sizeof(uint16_t) + passed_bytes)
- throw pe_exception("Incorrect resource string table", pe_exception::resource_incorrect_string_table);
-
- //Get string length - the first WORD
- uint16_t string_length = *reinterpret_cast<const uint16_t*>(resource_data.data() + passed_bytes);
- passed_bytes += sizeof(uint16_t); //WORD containing string length
-
- //Check resource data length again
- if(resource_data.length() < string_length + passed_bytes)
- throw pe_exception("Incorrect resource string table", pe_exception::resource_incorrect_string_table);
-
- if(string_length)
- {
- //Create and save string (UNICODE)
-#ifdef PE_BLISS_WINDOWS
- ret.insert(
- std::make_pair(static_cast<uint16_t>(((id - 1) << 4) + i), //ID of string is calculated such way
- std::wstring(reinterpret_cast<const wchar_t*>(resource_data.data() + passed_bytes), string_length)));
-#else
- ret.insert(
- std::make_pair(static_cast<uint16_t>(((id - 1) << 4) + i), //ID of string is calculated such way
- pe_utils::from_ucs2(u16string(reinterpret_cast<const unicode16_t*>(resource_data.data() + passed_bytes), string_length))));
-#endif
- }
-
- //Go to next string
- passed_bytes += string_length * 2;
- }
-
- return ret;
-}
-
-//Returns string from string table by ID and language
-const std::wstring resource_string_table_reader::get_string_by_id_lang(uint32_t language, uint16_t id) const
-{
- //List strings by string table id and language
- const resource_string_list strings(get_string_table_by_id_lang(language, (id >> 4) + 1));
- resource_string_list::const_iterator it = strings.find(id); //Find string by id
- if(it == strings.end())
- throw pe_exception("Resource string not found", pe_exception::resource_string_not_found);
-
- return (*it).second;
-}
-
-//Returns string from string table by ID and index in language directory (instead of language)
-const std::wstring resource_string_table_reader::get_string_by_id(uint16_t id, uint32_t index) const
-{
- //List strings by string table id and index
- const resource_string_list strings(get_string_table_by_id((id >> 4) + 1, index));
- resource_string_list::const_iterator it = strings.find(id); //Find string by id
- if(it == strings.end())
- throw pe_exception("Resource string not found", pe_exception::resource_string_not_found);
-
- return (*it).second;
-}
-}
diff --git a/tools/pe_bliss/resource_string_table_reader.h b/tools/pe_bliss/resource_string_table_reader.h
deleted file mode 100644
index e3ded1da85..0000000000
--- a/tools/pe_bliss/resource_string_table_reader.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <string>
-#include <map>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
-class pe_resource_viewer;
-
-//ID; string
-typedef std::map<uint16_t, std::wstring> resource_string_list;
-
-class resource_string_table_reader
-{
-public:
- resource_string_table_reader(const pe_resource_viewer& res);
-
-public:
- //Returns string table data by ID and language
- const resource_string_list get_string_table_by_id_lang(uint32_t language, uint32_t id) const;
- //Returns string table data by ID and index in language directory (instead of language)
- const resource_string_list get_string_table_by_id(uint32_t id, uint32_t index = 0) const;
- //Returns string from string table by ID and language
- const std::wstring get_string_by_id_lang(uint32_t language, uint16_t id) const;
- //Returns string from string table by ID and index in language directory (instead of language)
- const std::wstring get_string_by_id(uint16_t id, uint32_t index = 0) const;
-
-private:
- const pe_resource_viewer& res_;
-
- //Helper function of parsing string list table
- //Id of resource is needed to calculate string IDs correctly
- //resource_data is raw string table resource data
- static const resource_string_list parse_string_list(uint32_t id, const std::string& resource_data);
-};
-}
diff --git a/tools/pe_bliss/resource_version_info_reader.cpp b/tools/pe_bliss/resource_version_info_reader.cpp
deleted file mode 100644
index 8ad44c6856..0000000000
--- a/tools/pe_bliss/resource_version_info_reader.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "resource_version_info_reader.h"
-#include "utils.h"
-#include "pe_exception.h"
-#include "resource_internal.h"
-#include "pe_resource_viewer.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-//Root version info block key value
-const u16string resource_version_info_reader::version_info_key(U16TEXT("V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0"));
-
-resource_version_info_reader::resource_version_info_reader(const pe_resource_viewer& res)
- :res_(res)
-{}
-
-//Returns aligned version block value position
-uint32_t resource_version_info_reader::get_version_block_value_pos(uint32_t base_pos, const unicode16_t* key)
-{
- uint32_t string_length = static_cast<uint32_t>(u16string(key).length());
- uint32_t ret = pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 /* headers before Key data */
- + base_pos
- + (string_length + 1 /* nullbyte */) * 2),
- sizeof(uint32_t));
-
- //Check possible overflows
- if(ret < base_pos || ret < sizeof(uint16_t) * 3 || ret < (string_length + 1) * 2)
- throw_incorrect_version_info();
-
- return ret;
-}
-
-//Returns aligned version block first child position
-uint32_t resource_version_info_reader::get_version_block_first_child_pos(uint32_t base_pos, uint32_t value_length, const unicode16_t* key)
-{
- uint32_t string_length = static_cast<uint32_t>(u16string(key).length());
- uint32_t ret = pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 /* headers before Key data */
- + base_pos
- + (string_length + 1 /* nullbyte */) * 2),
- sizeof(uint32_t))
- + pe_utils::align_up(value_length, sizeof(uint32_t));
-
- //Check possible overflows
- if(ret < base_pos || ret < value_length || ret < sizeof(uint16_t) * 3 || ret < (string_length + 1) * 2)
- throw_incorrect_version_info();
-
- return ret;
-}
-
-//Throws an exception (id = resource_incorrect_version_info)
-void resource_version_info_reader::throw_incorrect_version_info()
-{
- throw pe_exception("Incorrect resource version info", pe_exception::resource_incorrect_version_info);
-}
-
-//Returns full version information:
-//file_version_info: versions and file info
-//lang_string_values_map: map of version info strings with encodings
-//translation_values_map: map of translations
-const file_version_info resource_version_info_reader::get_version_info(lang_string_values_map& string_values, translation_values_map& translations, const std::string& resource_data) const
-{
- //Fixed file version info
- file_version_info ret;
-
- //Check resource data length
- if(resource_data.length() < sizeof(version_info_block))
- throw_incorrect_version_info();
-
- //Root version info block
- const version_info_block* root_block = reinterpret_cast<const version_info_block*>(resource_data.data());
-
- //Check root block key for null-termination and its name
- if(!pe_utils::is_null_terminated(root_block->Key, resource_data.length() - sizeof(uint16_t) * 3 /* headers before Key data */)
- || version_info_key != reinterpret_cast<const unicode16_t*>(root_block->Key))
- throw_incorrect_version_info();
-
- //If file has fixed version info
- if(root_block->ValueLength)
- {
- //Get root block value position
- uint32_t value_pos = get_version_block_value_pos(0, reinterpret_cast<const unicode16_t*>(root_block->Key));
- //Check value length
- if(resource_data.length() < value_pos + sizeof(vs_fixedfileinfo))
- throw_incorrect_version_info();
-
- //Get VS_FIXEDFILEINFO structure pointer
- const vs_fixedfileinfo* file_info = reinterpret_cast<const vs_fixedfileinfo*>(resource_data.data() + value_pos);
- //Check its signature and some other fields
- if(file_info->dwSignature != vs_ffi_signature || file_info->dwStrucVersion != vs_ffi_strucversion) //Don't check if file_info->dwFileFlagsMask == VS_FFI_FILEFLAGSMASK
- throw_incorrect_version_info();
-
- //Save fixed version info
- ret = file_version_info(*file_info);
- }
-
- //Iterate over child elements of VS_VERSIONINFO (StringFileInfo or VarFileInfo)
- for(uint32_t child_pos = get_version_block_first_child_pos(0, root_block->ValueLength, reinterpret_cast<const unicode16_t*>(root_block->Key));
- child_pos < root_block->Length;)
- {
- //Check block position
- if(!pe_utils::is_sum_safe(child_pos, sizeof(version_info_block))
- || resource_data.length() < child_pos + sizeof(version_info_block))
- throw_incorrect_version_info();
-
- //Get VERSION_INFO_BLOCK structure pointer
- const version_info_block* block = reinterpret_cast<const version_info_block*>(resource_data.data() + child_pos);
-
- //Check its length
- if(block->Length == 0)
- throw_incorrect_version_info();
-
- //Check block key for null-termination
- if(!pe_utils::is_null_terminated(block->Key, resource_data.length() - child_pos - sizeof(uint16_t) * 3 /* headers before Key data */))
- throw_incorrect_version_info();
-
- u16string info_type(reinterpret_cast<const unicode16_t*>(block->Key));
- //If we encountered StringFileInfo...
- if(info_type == StringFileInfo)
- {
- //Enumerate all string tables
- for(uint32_t string_table_pos = get_version_block_first_child_pos(child_pos, block->ValueLength, reinterpret_cast<const unicode16_t*>(block->Key));
- string_table_pos - child_pos < block->Length;)
- {
- //Check string table block position
- if(resource_data.length() < string_table_pos + sizeof(version_info_block))
- throw_incorrect_version_info();
-
- //Get VERSION_INFO_BLOCK structure pointer for string table
- const version_info_block* string_table = reinterpret_cast<const version_info_block*>(resource_data.data() + string_table_pos);
-
- //Check its length
- if(string_table->Length == 0)
- throw_incorrect_version_info();
-
- //Check string table key for null-termination
- if(!pe_utils::is_null_terminated(string_table->Key, resource_data.length() - string_table_pos - sizeof(uint16_t) * 3 /* headers before Key data */))
- throw_incorrect_version_info();
-
- string_values_map new_values;
-
- //Enumerate all strings in the string table
- for(uint32_t string_pos = get_version_block_first_child_pos(string_table_pos, string_table->ValueLength, reinterpret_cast<const unicode16_t*>(string_table->Key));
- string_pos - string_table_pos < string_table->Length;)
- {
- //Check string block position
- if(resource_data.length() < string_pos + sizeof(version_info_block))
- throw_incorrect_version_info();
-
- //Get VERSION_INFO_BLOCK structure pointer for string block
- const version_info_block* string_block = reinterpret_cast<const version_info_block*>(resource_data.data() + string_pos);
-
- //Check its length
- if(string_block->Length == 0)
- throw_incorrect_version_info();
-
- //Check string block key for null-termination
- if(!pe_utils::is_null_terminated(string_block->Key, resource_data.length() - string_pos - sizeof(uint16_t) * 3 /* headers before Key data */))
- throw_incorrect_version_info();
-
- u16string data;
- //If string block has value
- if(string_block->ValueLength != 0)
- {
- //Get value position
- uint32_t value_pos = get_version_block_value_pos(string_pos, reinterpret_cast<const unicode16_t*>(string_block->Key));
- //Check it
- if(resource_data.length() < value_pos + string_block->ValueLength)
- throw pe_exception("Incorrect resource version info", pe_exception::resource_incorrect_version_info);
-
- //Get UNICODE string value
- data = u16string(reinterpret_cast<const unicode16_t*>(resource_data.data() + value_pos), string_block->ValueLength);
- pe_utils::strip_nullbytes(data);
- }
-
- //Save name-value pair
-#ifdef PE_BLISS_WINDOWS
- new_values.insert(std::make_pair(reinterpret_cast<const unicode16_t*>(string_block->Key), data));
-#else
- new_values.insert(std::make_pair(pe_utils::from_ucs2(reinterpret_cast<const unicode16_t*>(string_block->Key)),
- pe_utils::from_ucs2(data)));
-#endif
-
- //Navigate to next string block
- string_pos += pe_utils::align_up(string_block->Length, sizeof(uint32_t));
- }
-
-#ifdef PE_BLISS_WINDOWS
- string_values.insert(std::make_pair(reinterpret_cast<const unicode16_t*>(string_table->Key), new_values));
-#else
- string_values.insert(std::make_pair(pe_utils::from_ucs2(reinterpret_cast<const unicode16_t*>(string_table->Key)), new_values));
-#endif
-
- //Navigate to next string table block
- string_table_pos += pe_utils::align_up(string_table->Length, sizeof(uint32_t));
- }
- }
- else if(info_type == VarFileInfo) //If we encountered VarFileInfo
- {
- for(uint32_t var_table_pos = get_version_block_first_child_pos(child_pos, block->ValueLength, reinterpret_cast<const unicode16_t*>(block->Key));
- var_table_pos - child_pos < block->Length;)
- {
- //Check var block position
- if(resource_data.length() < var_table_pos + sizeof(version_info_block))
- throw_incorrect_version_info();
-
- //Get VERSION_INFO_BLOCK structure pointer for var block
- const version_info_block* var_table = reinterpret_cast<const version_info_block*>(resource_data.data() + var_table_pos);
-
- //Check its length
- if(var_table->Length == 0)
- throw_incorrect_version_info();
-
- //Check its key for null-termination
- if(!pe_utils::is_null_terminated(var_table->Key, resource_data.length() - var_table_pos - sizeof(uint16_t) * 3 /* headers before Key data */))
- throw_incorrect_version_info();
-
- //If block is "Translation" (actually, there's no other types possible in VarFileInfo) and it has value
- if(u16string(reinterpret_cast<const unicode16_t*>(var_table->Key)) == Translation && var_table->ValueLength)
- {
- //Get its value position
- uint32_t value_pos = get_version_block_value_pos(var_table_pos, reinterpret_cast<const unicode16_t*>(var_table->Key));
- //Cherck value length
- if(resource_data.length() < value_pos + var_table->ValueLength)
- throw_incorrect_version_info();
-
- //Get list of translations: pairs of LANGUAGE_ID - CODEPAGE_ID
- for(unsigned long i = 0; i < var_table->ValueLength; i += sizeof(uint16_t) * 2)
- {
- //Pair of WORDs
- uint16_t lang_id = *reinterpret_cast<const uint16_t*>(resource_data.data() + value_pos + i);
- uint16_t codepage_id = *reinterpret_cast<const uint16_t*>(resource_data.data() + value_pos + sizeof(uint16_t) + i);
- //Save translation
- translations.insert(std::make_pair(lang_id, codepage_id));
- }
- }
-
- //Navigate to next var block
- var_table_pos += pe_utils::align_up(var_table->Length, sizeof(uint32_t));
- }
- }
- else
- {
- throw_incorrect_version_info();
- }
-
- //Navigate to next element in root block
- child_pos += pe_utils::align_up(block->Length, sizeof(uint32_t));
- }
-
- return ret;
-}
-
-//Returns full version information:
-//file_version info: versions and file info
-//lang_string_values_map: map of version info strings with encodings
-//translation_values_map: map of translations
-const file_version_info resource_version_info_reader::get_version_info_by_lang(lang_string_values_map& string_values, translation_values_map& translations, uint32_t language) const
-{
- const std::string& resource_data = res_.get_root_directory() //Type directory
- .entry_by_id(pe_resource_viewer::resource_version)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(1)
- .get_resource_directory() //Language directory
- .entry_by_id(language)
- .get_data_entry() //Data directory
- .get_data();
-
- return get_version_info(string_values, translations, resource_data);
-}
-
-//Returns full version information:
-//file_version_info: versions and file info
-//lang_string_values_map: map of version info strings with encodings
-//translation_values_map: map of translations
-const file_version_info resource_version_info_reader::get_version_info(lang_string_values_map& string_values, translation_values_map& translations, uint32_t index) const
-{
- const resource_directory::entry_list& entries = res_.get_root_directory() //Type directory
- .entry_by_id(pe_resource_viewer::resource_version)
- .get_resource_directory() //Name/ID directory
- .entry_by_id(1)
- .get_resource_directory() //Language directory
- .get_entry_list();
-
- if(entries.size() <= index)
- throw pe_exception("Resource data entry not found", pe_exception::resource_data_entry_not_found);
-
- return get_version_info(string_values, translations, entries.at(index).get_data_entry().get_data()); //Data directory
-}
-}
diff --git a/tools/pe_bliss/resource_version_info_reader.h b/tools/pe_bliss/resource_version_info_reader.h
deleted file mode 100644
index c1dfbffdc2..0000000000
--- a/tools/pe_bliss/resource_version_info_reader.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <map>
-#include "file_version_info.h"
-#include "pe_structures.h"
-#include "version_info_types.h"
-
-namespace pe_bliss
-{
-class pe_resource_viewer;
-
-class resource_version_info_reader
-{
-public: //VERSION INFO
- resource_version_info_reader(const pe_resource_viewer& res);
-
- //Returns full version information:
- //file_version_info: versions and file info
- //lang_lang_string_values_map: map of version info strings with encodings with encodings
- //translation_values_map: map of translations
- const file_version_info get_version_info(lang_string_values_map& string_values, translation_values_map& translations, uint32_t index = 0) const;
- const file_version_info get_version_info_by_lang(lang_string_values_map& string_values, translation_values_map& translations, uint32_t language) const;
-
-public:
- //L"VS_VERSION_INFO" key of root version info block
- static const u16string version_info_key;
-
-private:
- const pe_resource_viewer& res_;
-
- //VERSION INFO helpers
- //Returns aligned version block value position
- static uint32_t get_version_block_value_pos(uint32_t base_pos, const unicode16_t* key);
-
- //Returns aligned version block first child position
- static uint32_t get_version_block_first_child_pos(uint32_t base_pos, uint32_t value_length, const unicode16_t* key);
-
- //Returns full version information:
- //file_version_info: versions and file info
- //lang_string_values_map: map of version info strings with encodings
- //translation_values_map: map of translations
- const file_version_info get_version_info(lang_string_values_map& string_values, translation_values_map& translations, const std::string& resource_data) const;
-
- //Throws an exception (id = resource_incorrect_version_info)
- static void throw_incorrect_version_info();
-};
-}
diff --git a/tools/pe_bliss/resource_version_info_writer.cpp b/tools/pe_bliss/resource_version_info_writer.cpp
deleted file mode 100644
index ed95a0f7ea..0000000000
--- a/tools/pe_bliss/resource_version_info_writer.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "resource_version_info_writer.h"
-#include "pe_structures.h"
-#include "resource_internal.h"
-#include "utils.h"
-#include "pe_resource_manager.h"
-#include "resource_version_info_reader.h"
-
-namespace pe_bliss
-{
-using namespace pe_win;
-
-resource_version_info_writer::resource_version_info_writer(pe_resource_manager& res)
- :res_(res)
-{}
-
-//Sets/replaces full version information:
-//file_version_info: versions and file info
-//lang_string_values_map: map of version info strings with encodings
-//translation_values_map: map of translations
-void resource_version_info_writer::set_version_info(const file_version_info& file_info,
- const lang_string_values_map& string_values,
- const translation_values_map& translations,
- uint32_t language,
- uint32_t codepage,
- uint32_t timestamp)
-{
- std::string version_data;
-
- //Calculate total size of version resource data
- uint32_t total_version_info_length =
- static_cast<uint32_t>(sizeof(version_info_block) - sizeof(uint16_t) + sizeof(uint16_t) /* pading */
- + (resource_version_info_reader::version_info_key.length() + 1) * 2
- + sizeof(vs_fixedfileinfo));
-
- //If we have any strings values
- if(!string_values.empty())
- {
- total_version_info_length += sizeof(version_info_block) - sizeof(uint16_t); //StringFileInfo block
- total_version_info_length += SizeofStringFileInfo; //Name of block (key)
-
- //Add required size for version strings
- for(lang_string_values_map::const_iterator table_it = string_values.begin(); table_it != string_values.end(); ++table_it)
- {
- total_version_info_length += pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 + ((*table_it).first.length() + 1) * 2), sizeof(uint32_t)); //Name of child block and block size (key of string table block)
-
- const string_values_map& values = (*table_it).second;
- for(string_values_map::const_iterator it = values.begin(); it != values.end(); ++it)
- {
- total_version_info_length += pe_utils::align_up(static_cast<uint32_t>(sizeof(uint16_t) * 3 + ((*it).first.length() + 1) * 2), sizeof(uint32_t));
- total_version_info_length += pe_utils::align_up(static_cast<uint32_t>(((*it).second.length() + 1) * 2), sizeof(uint32_t));
- }
- }
- }
-
- //If we have translations
- if(!translations.empty())
- {
- total_version_info_length += (sizeof(version_info_block) - sizeof(uint16_t)) * 2; //VarFileInfo and Translation blocks
- total_version_info_length += SizeofVarFileInfoAligned; //DWORD-aligned VarFileInfo block name
- total_version_info_length += SizeofTranslationAligned; //DWORD-aligned Translation block name
- total_version_info_length += static_cast<uint32_t>(translations.size() * sizeof(uint16_t) * 2);
- }
-
- //Resize version data buffer
- version_data.resize(total_version_info_length);
-
- //Create root version block
- version_info_block root_block = {0};
- root_block.ValueLength = sizeof(vs_fixedfileinfo);
- root_block.Length = static_cast<uint16_t>(total_version_info_length);
-
- //Fill fixed file info
- vs_fixedfileinfo fixed_info = {0};
- fixed_info.dwFileDateLS = file_info.get_file_date_ls();
- fixed_info.dwFileDateMS = file_info.get_file_date_ms();
- fixed_info.dwFileFlags = file_info.get_file_flags();
- fixed_info.dwFileFlagsMask = vs_ffi_fileflagsmask;
- fixed_info.dwFileOS = file_info.get_file_os_raw();
- fixed_info.dwFileSubtype = file_info.get_file_subtype();
- fixed_info.dwFileType = file_info.get_file_type_raw();
- fixed_info.dwFileVersionLS = file_info.get_file_version_ls();
- fixed_info.dwFileVersionMS = file_info.get_file_version_ms();
- fixed_info.dwSignature = vs_ffi_signature;
- fixed_info.dwStrucVersion = vs_ffi_strucversion;
- fixed_info.dwProductVersionLS = file_info.get_product_version_ls();
- fixed_info.dwProductVersionMS = file_info.get_product_version_ms();
-
- //Write root block and fixed file info to buffer
- uint32_t data_ptr = 0;
- memcpy(&version_data[data_ptr], &root_block, sizeof(version_info_block) - sizeof(uint16_t));
- data_ptr += sizeof(version_info_block) - sizeof(uint16_t);
- memcpy(&version_data[data_ptr], resource_version_info_reader::version_info_key.c_str(), (resource_version_info_reader::version_info_key.length() + 1) * sizeof(uint16_t));
- data_ptr += static_cast<uint32_t>((resource_version_info_reader::version_info_key.length() + 1) * sizeof(uint16_t));
- memset(&version_data[data_ptr], 0, sizeof(uint16_t));
- data_ptr += sizeof(uint16_t);
- memcpy(&version_data[data_ptr], &fixed_info, sizeof(fixed_info));
- data_ptr += sizeof(fixed_info);
-
- //Write string values, if any
- if(!string_values.empty())
- {
- //Create string file info root block
- version_info_block string_file_info_block = {0};
- string_file_info_block.Type = 1; //Block type is string
- memcpy(&version_data[data_ptr], &string_file_info_block, sizeof(version_info_block) - sizeof(uint16_t));
- //We will calculate its length later
- version_info_block* string_file_info_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]);
- data_ptr += sizeof(version_info_block) - sizeof(uint16_t);
-
- uint32_t old_ptr1 = data_ptr; //Used to calculate string file info block length later
- memcpy(&version_data[data_ptr], StringFileInfo, SizeofStringFileInfo); //Write block name
- data_ptr += SizeofStringFileInfo;
-
- //Create string table root block (child of string file info)
- version_info_block string_table_block = {0};
- string_table_block.Type = 1; //Block type is string
-
- for(lang_string_values_map::const_iterator table_it = string_values.begin(); table_it != string_values.end(); ++table_it)
- {
- const string_values_map& values = (*table_it).second;
-
- memcpy(&version_data[data_ptr], &string_table_block, sizeof(version_info_block) - sizeof(uint16_t));
- //We will calculate its length later
- version_info_block* string_table_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]);
- data_ptr += sizeof(version_info_block) - sizeof(uint16_t);
-
- uint32_t old_ptr2 = data_ptr; //Used to calculate string table block length later
- uint32_t lang_key_length = static_cast<uint32_t>(((*table_it).first.length() + 1) * sizeof(uint16_t));
-
-#ifdef PE_BLISS_WINDOWS
- memcpy(&version_data[data_ptr], (*table_it).first.c_str(), lang_key_length); //Write block key
-#else
- {
- u16string str(pe_utils::to_ucs2((*table_it).first));
- memcpy(&version_data[data_ptr], str.c_str(), lang_key_length); //Write block key
- }
-#endif
-
- data_ptr += lang_key_length;
- //Align key if necessary
- if((sizeof(uint16_t) * 3 + lang_key_length) % sizeof(uint32_t))
- {
- memset(&version_data[data_ptr], 0, sizeof(uint16_t));
- data_ptr += sizeof(uint16_t);
- }
-
- //Create string block (child of string table block)
- version_info_block string_block = {0};
- string_block.Type = 1; //Block type is string
- for(string_values_map::const_iterator it = values.begin(); it != values.end(); ++it)
- {
- //Calculate value length and key length of string block
- string_block.ValueLength = static_cast<uint16_t>((*it).second.length() + 1);
- uint32_t key_length = static_cast<uint32_t>(((*it).first.length() + 1) * sizeof(uint16_t));
- //Calculate length of block
- string_block.Length = static_cast<uint16_t>(pe_utils::align_up(sizeof(uint16_t) * 3 + key_length, sizeof(uint32_t)) + string_block.ValueLength * sizeof(uint16_t));
-
- //Write string block
- memcpy(&version_data[data_ptr], &string_block, sizeof(version_info_block) - sizeof(uint16_t));
- data_ptr += sizeof(version_info_block) - sizeof(uint16_t);
-
-#ifdef PE_BLISS_WINDOWS
- memcpy(&version_data[data_ptr], (*it).first.c_str(), key_length); //Write block key
-#else
- {
- u16string str(pe_utils::to_ucs2((*it).first));
- memcpy(&version_data[data_ptr], str.c_str(), key_length); //Write block key
- }
-#endif
-
- data_ptr += key_length;
- //Align key if necessary
- if((sizeof(uint16_t) * 3 + key_length) % sizeof(uint32_t))
- {
- memset(&version_data[data_ptr], 0, sizeof(uint16_t));
- data_ptr += sizeof(uint16_t);
- }
-
- //Write block data (value)
-#ifdef PE_BLISS_WINDOWS
- memcpy(&version_data[data_ptr], (*it).second.c_str(), string_block.ValueLength * sizeof(uint16_t));
-#else
- {
- u16string str(pe_utils::to_ucs2((*it).second));
- memcpy(&version_data[data_ptr], str.c_str(), string_block.ValueLength * sizeof(uint16_t));
- }
-#endif
-
- data_ptr += string_block.ValueLength * 2;
- //Align data if necessary
- if((string_block.ValueLength * 2) % sizeof(uint32_t))
- {
- memset(&version_data[data_ptr], 0, sizeof(uint16_t));
- data_ptr += sizeof(uint16_t);
- }
- }
-
- //Calculate string table and string file info blocks lengths
- string_table_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr2 + sizeof(uint16_t) * 3);
- }
-
- string_file_info_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr1 + sizeof(uint16_t) * 3);
- }
-
- //If we have transactions
- if(!translations.empty())
- {
- //Create root var file info block
- version_info_block var_file_info_block = {0};
- var_file_info_block.Type = 1; //Type of block is string
- //Write block header
- memcpy(&version_data[data_ptr], &var_file_info_block, sizeof(version_info_block) - sizeof(uint16_t));
- //We will calculate its length later
- version_info_block* var_file_info_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]);
- data_ptr += sizeof(version_info_block) - sizeof(uint16_t);
-
- uint32_t old_ptr1 = data_ptr; //Used to calculate var file info block length later
- memcpy(&version_data[data_ptr], VarFileInfoAligned, SizeofVarFileInfoAligned); //Write block key (aligned)
- data_ptr += SizeofVarFileInfoAligned;
-
- //Create root translation block (child of var file info block)
- version_info_block translation_block = {0};
- //Write block header
- memcpy(&version_data[data_ptr], &translation_block, sizeof(version_info_block) - sizeof(uint16_t));
- //We will calculate its length later
- version_info_block* translation_block_ptr = reinterpret_cast<version_info_block*>(&version_data[data_ptr]);
- data_ptr += sizeof(version_info_block) - sizeof(uint16_t);
-
- uint32_t old_ptr2 = data_ptr; //Used to calculate var file info block length later
- memcpy(&version_data[data_ptr], TranslationAligned, SizeofTranslationAligned); //Write block key (aligned)
- data_ptr += SizeofTranslationAligned;
-
- //Calculate translation block value length
- translation_block_ptr->ValueLength = static_cast<uint16_t>(sizeof(uint16_t) * 2 * translations.size());
-
- //Write translation values to block
- for(translation_values_map::const_iterator it = translations.begin(); it != translations.end(); ++it)
- {
- uint16_t lang_id = (*it).first; //Language ID
- uint16_t codepage_id = (*it).second; //Codepage ID
- memcpy(&version_data[data_ptr], &lang_id, sizeof(lang_id));
- data_ptr += sizeof(lang_id);
- memcpy(&version_data[data_ptr], &codepage_id, sizeof(codepage_id));
- data_ptr += sizeof(codepage_id);
- }
-
- //Calculate Translation and VarFileInfo blocks lengths
- translation_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr2 + sizeof(uint16_t) * 3);
- var_file_info_block_ptr->Length = static_cast<uint16_t>(data_ptr - old_ptr1 + sizeof(uint16_t) * 3);
- }
-
- //Add/replace version info resource
- res_.add_resource(version_data, pe_resource_viewer::resource_version, 1, language, codepage, timestamp);
-}
-
-//Removes version info by language (ID = 1)
-bool resource_version_info_writer::remove_version_info(uint32_t language)
-{
- return res_.remove_resource(pe_resource_viewer::resource_version, 1, language);
-}
-}
diff --git a/tools/pe_bliss/resource_version_info_writer.h b/tools/pe_bliss/resource_version_info_writer.h
deleted file mode 100644
index da279ddedb..0000000000
--- a/tools/pe_bliss/resource_version_info_writer.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include "version_info_types.h"
-#include "file_version_info.h"
-
-namespace pe_bliss
-{
-class pe_resource_manager;
-
-class resource_version_info_writer
-{
-public:
- resource_version_info_writer(pe_resource_manager& res);
-
- //Sets/replaces full version information:
- //file_version_info: versions and file info
- //lang_string_values_map: map of version info strings with encodings
- //translation_values_map: map of translations
- void set_version_info(const file_version_info& file_info,
- const lang_string_values_map& string_values,
- const translation_values_map& translations,
- uint32_t language,
- uint32_t codepage = 0,
- uint32_t timestamp = 0);
-
- //Removes version info by language (ID = 1)
- bool remove_version_info(uint32_t language);
-
-private:
- pe_resource_manager& res_;
-};
-}
diff --git a/tools/pe_bliss/stdint_defs.h b/tools/pe_bliss/stdint_defs.h
deleted file mode 100644
index bbc003690a..0000000000
--- a/tools/pe_bliss/stdint_defs.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#ifdef _MSC_VER
-#if _MSC_VER < 1600
-namespace pe_bliss
-{
- //stdint.h definitions for MSVC 2008 and earlier, as
- //it doesn't have them
- typedef signed char int8_t;
- typedef short int16_t;
- typedef int int32_t;
-
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int uint32_t;
-
- typedef long long int64_t;
- typedef unsigned long long uint64_t;
-}
-#else
-#include <stdint.h>
-#endif
-#else
-#include <stdint.h>
-#endif
diff --git a/tools/pe_bliss/utils.cpp b/tools/pe_bliss/utils.cpp
deleted file mode 100644
index e6a75d5497..0000000000
--- a/tools/pe_bliss/utils.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <string.h>
-#include "utils.h"
-#include "pe_exception.h"
-
-
-namespace pe_bliss
-{
-const double pe_utils::log_2 = 1.44269504088896340736; //instead of using M_LOG2E
-
-//Returns stream size
-std::streamoff pe_utils::get_file_size(std::istream& file)
-{
- //Get old istream offset
- std::streamoff old_offset = file.tellg();
- file.seekg(0, std::ios::end);
- std::streamoff filesize = file.tellg();
- //Set old istream offset
- file.seekg(old_offset);
- return filesize;
-}
-
-#ifndef PE_BLISS_WINDOWS
-const u16string pe_utils::to_ucs2(const std::wstring& str)
-{
- u16string ret;
- if(str.empty())
- return ret;
-
- int len = str.length();
-
- ret.resize(len);
-
- for(int i=0;i<len;i++) {
- ret[i]=str[i]&0xFFFF;
- }
-
- return ret;
-}
-
-const std::wstring pe_utils::from_ucs2(const u16string& str)
-{
- std::wstring ret;
- if(str.empty())
- return ret;
-
- int len = str.length();
- ret.resize(str.length());
-
- for(int i=0;i<len;i++) {
- ret[i]=str[i];
- }
-
- return ret;
-}
-#endif
-
-bool operator==(const pe_win::guid& guid1, const pe_win::guid& guid2)
-{
- return guid1.Data1 == guid2.Data1
- && guid1.Data2 == guid2.Data2
- && guid1.Data3 == guid2.Data3
- && !memcmp(guid1.Data4, guid2.Data4, sizeof(guid1.Data4));
-}
-}
diff --git a/tools/pe_bliss/utils.h b/tools/pe_bliss/utils.h
deleted file mode 100644
index 29125f8dc1..0000000000
--- a/tools/pe_bliss/utils.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <istream>
-#include <string>
-#include "stdint_defs.h"
-#include "pe_structures.h"
-
-namespace pe_bliss
-{
-class pe_utils
-{
-public:
- //Returns true if string "data" with maximum length "raw_length" is null-terminated
- template<typename T>
- static bool is_null_terminated(const T* data, size_t raw_length)
- {
- raw_length /= sizeof(T);
- for(size_t l = 0; l < raw_length; l++)
- {
- if(data[l] == static_cast<T>(L'\0'))
- return true;
- }
-
- return false;
- }
-
- //Helper template function to strip nullbytes in the end of string
- template<typename T>
- static void strip_nullbytes(std::basic_string<T>& str)
- {
- while(!*(str.end() - 1) && !str.empty())
- str.erase(str.length() - 1);
- }
-
- //Helper function to determine if number is power of 2
- template<typename T>
- static inline bool is_power_of_2(T x)
- {
- return !(x & (x - 1));
- }
-
- //Helper function to align number down
- template<typename T>
- static inline T align_down(T x, uint32_t align)
- {
- return x & ~(static_cast<T>(align) - 1);
- }
-
- //Helper function to align number up
- template<typename T>
- static inline T align_up(T x, uint32_t align)
- {
- return (x & static_cast<T>(align - 1)) ? align_down(x, align) + static_cast<T>(align) : x;
- }
-
- //Returns true if sum of two unsigned integers is safe (no overflow occurs)
- static inline bool is_sum_safe(uint32_t a, uint32_t b)
- {
- return a <= static_cast<uint32_t>(-1) - b;
- }
-
- //Two gigabytes value in bytes
- static const uint32_t two_gb = 0x80000000;
- static const uint32_t max_dword = 0xFFFFFFFF;
- static const uint32_t max_word = 0x0000FFFF;
- static const double log_2; //instead of using M_LOG2E
-
- //Returns stream size
- static std::streamoff get_file_size(std::istream& file);
-
-#ifndef PE_BLISS_WINDOWS
-public:
- static const u16string to_ucs2(const std::wstring& str);
- static const std::wstring from_ucs2(const u16string& str);
-#endif
-
-private:
- pe_utils();
- pe_utils(pe_utils&);
- pe_utils& operator=(const pe_utils&);
-};
-
-//Windows GUID comparison
-bool operator==(const pe_win::guid& guid1, const pe_win::guid& guid2);
-}
diff --git a/tools/pe_bliss/version_info_editor.cpp b/tools/pe_bliss/version_info_editor.cpp
deleted file mode 100644
index 199eebfd54..0000000000
--- a/tools/pe_bliss/version_info_editor.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <sstream>
-#include <iomanip>
-#include "version_info_types.h"
-#include "version_info_editor.h"
-#include "version_info_viewer.h"
-
-namespace pe_bliss
-{
-//Default constructor
-//strings - version info strings with charsets
-//translations - version info translations map
-version_info_editor::version_info_editor(lang_string_values_map& strings, translation_values_map& translations)
- :version_info_viewer(strings, translations),
- strings_edit_(strings),
- translations_edit_(translations)
-{}
-
-//Below functions have parameter translation
-//If it's empty, the default language translation will be taken
-//If there's no default language translation, the first one will be taken
-
-//Sets company name
-void version_info_editor::set_company_name(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"CompanyName", value, translation);
-}
-
-//Sets file description
-void version_info_editor::set_file_description(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"FileDescription", value, translation);
-}
-
-//Sets file version
-void version_info_editor::set_file_version(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"FileVersion", value, translation);
-}
-
-//Sets internal file name
-void version_info_editor::set_internal_name(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"InternalName", value, translation);
-}
-
-//Sets legal copyright
-void version_info_editor::set_legal_copyright(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"LegalCopyright", value, translation);
-}
-
-//Sets original file name
-void version_info_editor::set_original_filename(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"OriginalFilename", value, translation);
-}
-
-//Sets product name
-void version_info_editor::set_product_name(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"ProductName", value, translation);
-}
-
-//Sets product version
-void version_info_editor::set_product_version(const std::wstring& value, const std::wstring& translation)
-{
- set_property(L"ProductVersion", value, translation);
-}
-
-//Sets version info property value
-//property_name - property name
-//value - property value
-//If translation does not exist, it will be added
-//If property does not exist, it will be added
-void version_info_editor::set_property(const std::wstring& property_name, const std::wstring& value, const std::wstring& translation)
-{
- lang_string_values_map::iterator it = strings_edit_.begin();
-
- if(translation.empty())
- {
- //If no translation was specified
- it = strings_edit_.find(default_language_translation); //Find default translation table
- if(it == strings_edit_.end()) //If there's no default translation table, take the first one
- {
- it = strings_edit_.begin();
- if(it == strings_edit_.end()) //If there's no any translation table, add default one
- {
- it = strings_edit_.insert(std::make_pair(default_language_translation, string_values_map())).first;
- //Also add it to translations list
- add_translation(default_language_translation);
- }
- }
- }
- else
- {
- it = strings_edit_.find(translation); //Find specified translation table
- if(it == strings_edit_.end()) //If there's no translation, add it
- {
- it = strings_edit_.insert(std::make_pair(translation, string_values_map())).first;
- //Also add it to translations list
- add_translation(translation);
- }
- }
-
- //Change value of the required property
- ((*it).second)[property_name] = value;
-}
-
-//Adds translation to translation list
-void version_info_editor::add_translation(const std::wstring& translation)
-{
- std::pair<uint16_t, uint16_t> translation_ids(translation_from_string(translation));
- add_translation(translation_ids.first, translation_ids.second);
-}
-
-void version_info_editor::add_translation(uint16_t language_id, uint16_t codepage_id)
-{
- std::pair<translation_values_map::const_iterator, translation_values_map::const_iterator>
- range(translations_edit_.equal_range(language_id));
-
- //If translation already exists
- for(translation_values_map::const_iterator it = range.first; it != range.second; ++it)
- {
- if((*it).second == codepage_id)
- return;
- }
-
- translations_edit_.insert(std::make_pair(language_id, codepage_id));
-}
-
-//Removes translation from translations and strings lists
-void version_info_editor::remove_translation(const std::wstring& translation)
-{
- std::pair<uint16_t, uint16_t> translation_ids(translation_from_string(translation));
- remove_translation(translation_ids.first, translation_ids.second);
-}
-
-void version_info_editor::remove_translation(uint16_t language_id, uint16_t codepage_id)
-{
- {
- //Erase string table (if exists)
- std::wstringstream ss;
- ss << std::hex
- << std::setw(4) << std::setfill(L'0') << language_id
- << std::setw(4) << std::setfill(L'0') << codepage_id;
-
- strings_edit_.erase(ss.str());
- }
-
- //Find and erase translation from translations table
- std::pair<translation_values_map::iterator, translation_values_map::iterator>
- it_pair = translations_edit_.equal_range(language_id);
-
- for(translation_values_map::iterator it = it_pair.first; it != it_pair.second; ++it)
- {
- if((*it).second == codepage_id)
- {
- translations_edit_.erase(it);
- break;
- }
- }
-}
-}
diff --git a/tools/pe_bliss/version_info_editor.h b/tools/pe_bliss/version_info_editor.h
deleted file mode 100644
index 53d3dc62c1..0000000000
--- a/tools/pe_bliss/version_info_editor.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include "version_info_types.h"
-#include "version_info_viewer.h"
-
-namespace pe_bliss
-{
- //Helper class to read and edit version information
- //lang_string_values_map: map of version info strings with encodings
- //translation_values_map: map of translations
- class version_info_editor : public version_info_viewer
- {
- public:
- //Default constructor
- //strings - version info strings with charsets
- //translations - version info translations map
- version_info_editor(lang_string_values_map& strings, translation_values_map& translations);
-
- //Below functions have parameter translation
- //If it's empty, the default language translation will be taken
- //If there's no default language translation, the first one will be taken
-
- //Sets company name
- void set_company_name(const std::wstring& value, const std::wstring& translation = std::wstring());
- //Sets file description
- void set_file_description(const std::wstring& value, const std::wstring& translation = std::wstring());
- //Sets file version
- void set_file_version(const std::wstring& value, const std::wstring& translation = std::wstring());
- //Sets internal file name
- void set_internal_name(const std::wstring& value, const std::wstring& translation = std::wstring());
- //Sets legal copyright
- void set_legal_copyright(const std::wstring& value, const std::wstring& translation = std::wstring());
- //Sets original file name
- void set_original_filename(const std::wstring& value, const std::wstring& translation = std::wstring());
- //Sets product name
- void set_product_name(const std::wstring& value, const std::wstring& translation = std::wstring());
- //Sets product version
- void set_product_version(const std::wstring& value, const std::wstring& translation = std::wstring());
-
- //Sets version info property value
- //property_name - property name
- //value - property value
- //If translation does not exist, it will be added to strings and translations lists
- //If property does not exist, it will be added
- void set_property(const std::wstring& property_name, const std::wstring& value, const std::wstring& translation = std::wstring());
-
- //Adds translation to translation list
- void add_translation(const std::wstring& translation);
- void add_translation(uint16_t language_id, uint16_t codepage_id);
-
- //Removes translation from translations and strings lists
- void remove_translation(const std::wstring& translation);
- void remove_translation(uint16_t language_id, uint16_t codepage_id);
-
- private:
- lang_string_values_map& strings_edit_;
- translation_values_map& translations_edit_;
- };
-}
diff --git a/tools/pe_bliss/version_info_types.h b/tools/pe_bliss/version_info_types.h
deleted file mode 100644
index 6010c9691e..0000000000
--- a/tools/pe_bliss/version_info_types.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <map>
-#include <string>
-#include "stdint_defs.h"
-
-namespace pe_bliss
-{
- //Typedef for version info functions: Name - Value
- typedef std::map<std::wstring, std::wstring> string_values_map;
- //Typedef for version info functions: Language string - String Values Map
- //Language String consists of LangID and CharsetID
- //E.g. 041904b0 for Russian UNICODE, 040004b0 for Process Default Language UNICODE
- typedef std::map<std::wstring, string_values_map> lang_string_values_map;
-
- //Typedef for version info functions: Language - Character Set
- typedef std::multimap<uint16_t, uint16_t> translation_values_map;
-}
diff --git a/tools/pe_bliss/version_info_viewer.cpp b/tools/pe_bliss/version_info_viewer.cpp
deleted file mode 100644
index 6e2d0d5c5b..0000000000
--- a/tools/pe_bliss/version_info_viewer.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include <iomanip>
-#include <sstream>
-#include "pe_exception.h"
-#include "version_info_viewer.h"
-
-namespace pe_bliss
-{
-//Default process language, UNICODE
-const std::wstring version_info_viewer::default_language_translation(L"040904b0");
-
-//Default constructor
-//strings - version info strings with charsets
-//translations - version info translations map
-version_info_viewer::version_info_viewer(const lang_string_values_map& strings, const translation_values_map& translations)
- :strings_(strings), translations_(translations)
-{}
-
-//Below functions have parameter translation
-//If it's empty, the default language translation will be taken
-//If there's no default language translation, the first one will be taken
-
-//Returns company name
-const std::wstring version_info_viewer::get_company_name(const std::wstring& translation) const
-{
- return get_property(L"CompanyName", translation);
-}
-
-//Returns file description
-const std::wstring version_info_viewer::get_file_description(const std::wstring& translation) const
-{
- return get_property(L"FileDescription", translation);
-}
-
-//Returns file version
-const std::wstring version_info_viewer::get_file_version(const std::wstring& translation) const
-{
- return get_property(L"FileVersion", translation);
-}
-
-//Returns internal file name
-const std::wstring version_info_viewer::get_internal_name(const std::wstring& translation) const
-{
- return get_property(L"InternalName", translation);
-}
-
-//Returns legal copyright
-const std::wstring version_info_viewer::get_legal_copyright(const std::wstring& translation) const
-{
- return get_property(L"LegalCopyright", translation);
-}
-
-//Returns original file name
-const std::wstring version_info_viewer::get_original_filename(const std::wstring& translation) const
-{
- return get_property(L"OriginalFilename", translation);
-}
-
-//Returns product name
-const std::wstring version_info_viewer::get_product_name(const std::wstring& translation) const
-{
- return get_property(L"ProductName", translation);
-}
-
-//Returns product version
-const std::wstring version_info_viewer::get_product_version(const std::wstring& translation) const
-{
- return get_property(L"ProductVersion", translation);
-}
-
-//Returns list of translations in string representation
-const version_info_viewer::translation_list version_info_viewer::get_translation_list() const
-{
- translation_list ret;
-
- //Enumerate all translations
- for(translation_values_map::const_iterator it = translations_.begin(); it != translations_.end(); ++it)
- {
- //Create string representation of translation value
- std::wstringstream ss;
- ss << std::hex
- << std::setw(4) << std::setfill(L'0') << (*it).first
- << std::setw(4) << std::setfill(L'0') << (*it).second;
-
- //Save it
- ret.push_back(ss.str());
- }
-
- return ret;
-}
-
-//Returns version info property value
-//property_name - required property name
-//If throw_if_absent = true, will throw exception if property does not exist
-//If throw_if_absent = false, will return empty string if property does not exist
-const std::wstring version_info_viewer::get_property(const std::wstring& property_name, const std::wstring& translation, bool throw_if_absent) const
-{
- std::wstring ret;
-
- //If there're no strings
- if(strings_.empty())
- {
- if(throw_if_absent)
- throw pe_exception("Version info string does not exist", pe_exception::version_info_string_does_not_exist);
-
- return ret;
- }
-
- lang_string_values_map::const_iterator it = strings_.begin();
-
- if(translation.empty())
- {
- //If no translation was specified
- it = strings_.find(default_language_translation); //Find default translation table
- if(it == strings_.end()) //If there's no default translation table, take the first one
- it = strings_.begin();
- }
- else
- {
- it = strings_.find(translation); //Find specified translation table
- if(it == strings_.end())
- {
- if(throw_if_absent)
- throw pe_exception("Version info string does not exist", pe_exception::version_info_string_does_not_exist);
-
- return ret;
- }
- }
-
- //Find value of the required property
- string_values_map::const_iterator str_it = (*it).second.find(property_name);
-
- if(str_it == (*it).second.end())
- {
- if(throw_if_absent)
- throw pe_exception("Version info string does not exist", pe_exception::version_info_string_does_not_exist);
-
- return ret;
- }
-
- ret = (*str_it).second;
-
- return ret;
-}
-
-//Converts translation HEX-string to pair of language ID and codepage ID
-const version_info_viewer::translation_pair version_info_viewer::translation_from_string(const std::wstring& translation)
-{
- uint32_t translation_id = 0;
-
- {
- //Convert string to DWORD
- std::wstringstream ss;
- ss << std::hex << translation;
- ss >> translation_id;
- }
-
- return std::make_pair(static_cast<uint16_t>(translation_id >> 16), static_cast<uint16_t>(translation_id & 0xFFFF));
-}
-}
diff --git a/tools/pe_bliss/version_info_viewer.h b/tools/pe_bliss/version_info_viewer.h
deleted file mode 100644
index bc2f6f2ba7..0000000000
--- a/tools/pe_bliss/version_info_viewer.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*************************************************************************/
-/* Copyright (c) 2015 dx, http://kaimi.ru */
-/* */
-/* Permission is hereby granted, free of charge, to any person */
-/* obtaining a copy of this software and associated documentation */
-/* files (the "Software"), to deal in the Software without */
-/* restriction, including without limitation the rights to use, */
-/* copy, modify, merge, publish, distribute, sublicense, and/or */
-/* sell copies of the Software, and to permit persons to whom the */
-/* Software is furnished to do so, subject to the following conditions: */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#pragma once
-#include <map>
-#include <vector>
-#include <string>
-#include "pe_resource_viewer.h"
-#include "pe_structures.h"
-#include "version_info_types.h"
-
-namespace pe_bliss
-{
-//Helper class to read version information
-//lang_string_values_map: map of version info strings with encodings
-//translation_values_map: map of translations
-class version_info_viewer
-{
-public:
- //Useful typedefs
- typedef std::pair<uint16_t, uint16_t> translation_pair;
- typedef std::vector<std::wstring> translation_list;
-
-public:
- //Default constructor
- //strings - version info strings with charsets
- //translations - version info translations map
- version_info_viewer(const lang_string_values_map& strings, const translation_values_map& translations);
-
- //Below functions have parameter translation
- //If it's empty, the default language translation will be taken
- //If there's no default language translation, the first one will be taken
-
- //Returns company name
- const std::wstring get_company_name(const std::wstring& translation = std::wstring()) const;
- //Returns file description
- const std::wstring get_file_description(const std::wstring& translation = std::wstring()) const;
- //Returns file version
- const std::wstring get_file_version(const std::wstring& translation = std::wstring()) const;
- //Returns internal file name
- const std::wstring get_internal_name(const std::wstring& translation = std::wstring()) const;
- //Returns legal copyright
- const std::wstring get_legal_copyright(const std::wstring& translation = std::wstring()) const;
- //Returns original file name
- const std::wstring get_original_filename(const std::wstring& translation = std::wstring()) const;
- //Returns product name
- const std::wstring get_product_name(const std::wstring& translation = std::wstring()) const;
- //Returns product version
- const std::wstring get_product_version(const std::wstring& translation = std::wstring()) const;
-
- //Returns list of translations in string representation
- const translation_list get_translation_list() const;
-
- //Returns version info property value
- //property_name - required property name
- //If throw_if_absent = true, will throw exception if property does not exist
- //If throw_if_absent = false, will return empty string if property does not exist
- const std::wstring get_property(const std::wstring& property_name, const std::wstring& translation = std::wstring(), bool throw_if_absent = false) const;
-
- //Converts translation HEX-string to pair of language ID and codepage ID
- static const translation_pair translation_from_string(const std::wstring& translation);
-
-public:
- //Default process language, UNICODE
- static const std::wstring default_language_translation;
-
-private:
- const lang_string_values_map& strings_;
- const translation_values_map& translations_;
-};
-}
diff --git a/tools/scripts/sort-demos.sh b/tools/scripts/sort-demos.sh
new file mode 100644
index 0000000000..d4770b337e
--- /dev/null
+++ b/tools/scripts/sort-demos.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# When scanning for demos, the project manager sorts them based on their
+# timestamp, i.e. last modification date. This can make for a pretty
+# messy output, so this script 'touches' each engine.cfg file in reverse
+# alphabetical order to ensure a nice listing.
+#
+# It's good practice to run it once before packaging demos on the build
+# server.
+
+if [ ! -d "demos" ]; then
+ echo "Run this script from the root directory where 'demos/' is contained."
+ exit 1
+fi
+
+if [ -e demos.list ]; then
+ rm -f demos.list
+fi
+
+for dir in 2d 3d gui misc viewport; do
+ find "demos/$dir" -name "engine.cfg" |sort >> demos.list
+done
+cat demos.list |sort -r > demos_r.list
+
+while read line; do
+ touch $line
+ sleep 0.2
+done < demos_r.list
+
+#rm -f demos.list demos_r.list
diff --git a/tools/steam/community_capsule.jpg b/tools/steam/community_capsule.jpg
new file mode 100644
index 0000000000..abbc4793f7
--- /dev/null
+++ b/tools/steam/community_capsule.jpg
Binary files differ
diff --git a/tools/steam/community_capsule.png b/tools/steam/community_capsule.png
new file mode 100644
index 0000000000..ec9fa0a930
--- /dev/null
+++ b/tools/steam/community_capsule.png
Binary files differ
diff --git a/tools/steam/header.png b/tools/steam/header.png
new file mode 100644
index 0000000000..547b28df8d
--- /dev/null
+++ b/tools/steam/header.png
Binary files differ
diff --git a/tools/steam/icon32.icns b/tools/steam/icon32.icns
new file mode 100644
index 0000000000..6234e7d5ac
--- /dev/null
+++ b/tools/steam/icon32.icns
@@ -0,0 +1,1029 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="32" height="32">
+ <circle cx="0" cy="0" r="1" fill="white"/>
+ <circle cx="1" cy="0" r="1" fill="white"/>
+ <circle cx="2" cy="0" r="1" fill="white"/>
+ <circle cx="3" cy="0" r="1" fill="rgba(99.4095%,99.3835%,99.3835%,1)"/>
+ <circle cx="4" cy="0" r="1" fill="rgba(93.6355%,93.3593%,93.3593%,1)"/>
+ <circle cx="5" cy="0" r="1" fill="rgba(86.1707%,85.568%,85.568%,1)"/>
+ <circle cx="6" cy="0" r="1" fill="rgba(83.0671%,82.3316%,82.3316%,1)"/>
+ <circle cx="7" cy="0" r="1" fill="rgba(82.8702%,82.1271%,82.1271%,1)"/>
+ <circle cx="8" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="9" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="10" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="11" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="12" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="13" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="14" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="15" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="16" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="17" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="18" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="19" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="20" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="21" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="22" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="23" cy="0" r="1" fill="rgba(82.884%,82.1408%,82.1408%,1)"/>
+ <circle cx="24" cy="0" r="1" fill="rgba(82.8779%,82.1332%,82.1332%,1)"/>
+ <circle cx="25" cy="0" r="1" fill="rgba(82.9374%,82.1958%,82.1958%,1)"/>
+ <circle cx="26" cy="0" r="1" fill="rgba(85.2064%,84.5624%,84.5624%,1)"/>
+ <circle cx="27" cy="0" r="1" fill="rgba(92.0974%,91.754%,91.754%,1)"/>
+ <circle cx="28" cy="0" r="1" fill="rgba(98.8174%,98.7655%,98.7655%,1)"/>
+ <circle cx="29" cy="0" r="1" fill="white"/>
+ <circle cx="30" cy="0" r="1" fill="white"/>
+ <circle cx="31" cy="0" r="1" fill="white"/>
+ <circle cx="0" cy="1" r="1" fill="white"/>
+ <circle cx="1" cy="1" r="1" fill="white"/>
+ <circle cx="2" cy="1" r="1" fill="rgba(96.3653%,96.2066%,96.2066%,1)"/>
+ <circle cx="3" cy="1" r="1" fill="rgba(80.1495%,79.2859%,79.2859%,1)"/>
+ <circle cx="4" cy="1" r="1" fill="rgba(67.9744%,66.5827%,66.5827%,1)"/>
+ <circle cx="5" cy="1" r="1" fill="rgba(64.5335%,62.9908%,62.9908%,1)"/>
+ <circle cx="6" cy="1" r="1" fill="rgba(63.9979%,62.4308%,62.4308%,1)"/>
+ <circle cx="7" cy="1" r="1" fill="rgba(63.9811%,62.414%,62.414%,1)"/>
+ <circle cx="8" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="9" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="10" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="11" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="12" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="13" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="14" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="15" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="16" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="17" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="18" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="19" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="20" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="21" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="22" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="23" cy="1" r="1" fill="rgba(63.9826%,62.4155%,62.4155%,1)"/>
+ <circle cx="24" cy="1" r="1" fill="rgba(63.9811%,62.414%,62.414%,1)"/>
+ <circle cx="25" cy="1" r="1" fill="rgba(63.9841%,62.417%,62.417%,1)"/>
+ <circle cx="26" cy="1" r="1" fill="rgba(64.329%,62.7771%,62.7771%,1)"/>
+ <circle cx="27" cy="1" r="1" fill="rgba(66.8711%,65.4322%,65.4322%,1)"/>
+ <circle cx="28" cy="1" r="1" fill="rgba(77.0367%,76.0388%,76.0388%,1)"/>
+ <circle cx="29" cy="1" r="1" fill="rgba(94.0887%,93.8323%,93.8323%,1)"/>
+ <circle cx="30" cy="1" r="1" fill="white"/>
+ <circle cx="31" cy="1" r="1" fill="white"/>
+ <circle cx="0" cy="2" r="1" fill="white"/>
+ <circle cx="1" cy="2" r="1" fill="rgba(96.4508%,96.2966%,96.2966%,1)"/>
+ <circle cx="2" cy="2" r="1" fill="rgba(74.4732%,73.3623%,73.3623%,1)"/>
+ <circle cx="3" cy="2" r="1" fill="rgba(63.5355%,61.9501%,61.9501%,1)"/>
+ <circle cx="4" cy="2" r="1" fill="rgba(63.6469%,62.0661%,62.0661%,1)"/>
+ <circle cx="5" cy="2" r="1" fill="rgba(63.8956%,62.3255%,62.3255%,1)"/>
+ <circle cx="6" cy="2" r="1" fill="rgba(63.9185%,62.3499%,62.3499%,1)"/>
+ <circle cx="7" cy="2" r="1" fill="rgba(63.9185%,62.3499%,62.3499%,1)"/>
+ <circle cx="8" cy="2" r="1" fill="rgba(63.9185%,62.3499%,62.3499%,1)"/>
+ <circle cx="9" cy="2" r="1" fill="rgba(63.917%,62.3499%,62.3499%,1)"/>
+ <circle cx="10" cy="2" r="1" fill="rgba(63.9353%,62.3529%,62.3438%,1)"/>
+ <circle cx="11" cy="2" r="1" fill="rgba(64.1657%,62.4002%,62.2644%,1)"/>
+ <circle cx="12" cy="2" r="1" fill="rgba(64.4846%,62.4674%,62.153%,1)"/>
+ <circle cx="13" cy="2" r="1" fill="rgba(64.3595%,62.4414%,62.1973%,1)"/>
+ <circle cx="14" cy="2" r="1" fill="rgba(63.9475%,62.356%,62.3392%,1)"/>
+ <circle cx="15" cy="2" r="1" fill="rgba(63.917%,62.3499%,62.3499%,1)"/>
+ <circle cx="16" cy="2" r="1" fill="rgba(63.9185%,62.3499%,62.3499%,1)"/>
+ <circle cx="17" cy="2" r="1" fill="rgba(63.9094%,62.3484%,62.3529%,1)"/>
+ <circle cx="18" cy="2" r="1" fill="rgba(64.0864%,62.385%,62.2919%,1)"/>
+ <circle cx="19" cy="2" r="1" fill="rgba(64.4923%,62.4689%,62.15%,1)"/>
+ <circle cx="20" cy="2" r="1" fill="rgba(64.3732%,62.4445%,62.1912%,1)"/>
+ <circle cx="21" cy="2" r="1" fill="rgba(64.0299%,62.3728%,62.3117%,1)"/>
+ <circle cx="22" cy="2" r="1" fill="rgba(63.917%,62.3499%,62.3499%,1)"/>
+ <circle cx="23" cy="2" r="1" fill="rgba(63.9185%,62.3499%,62.3499%,1)"/>
+ <circle cx="24" cy="2" r="1" fill="rgba(63.9185%,62.3499%,62.3499%,1)"/>
+ <circle cx="25" cy="2" r="1" fill="rgba(63.9185%,62.3499%,62.3499%,1)"/>
+ <circle cx="26" cy="2" r="1" fill="rgba(63.9063%,62.3362%,62.3362%,1)"/>
+ <circle cx="27" cy="2" r="1" fill="rgba(63.7293%,62.153%,62.153%,1)"/>
+ <circle cx="28" cy="2" r="1" fill="rgba(63.3249%,61.7304%,61.7304%,1)"/>
+ <circle cx="29" cy="2" r="1" fill="rgba(70.7195%,69.4453%,69.4453%,1)"/>
+ <circle cx="30" cy="2" r="1" fill="rgba(93.5225%,93.2418%,93.2418%,1)"/>
+ <circle cx="31" cy="2" r="1" fill="white"/>
+ <circle cx="0" cy="3" r="1" fill="rgba(99.7345%,99.7223%,99.7223%,1)"/>
+ <circle cx="1" cy="3" r="1" fill="rgba(80.4944%,79.6475%,79.6475%,1)"/>
+ <circle cx="2" cy="3" r="1" fill="rgba(63.5645%,61.9806%,61.9806%,1)"/>
+ <circle cx="3" cy="3" r="1" fill="rgba(63.8788%,62.3072%,62.3072%,1)"/>
+ <circle cx="4" cy="3" r="1" fill="rgba(63.9231%,62.3545%,62.3545%,1)"/>
+ <circle cx="5" cy="3" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="6" cy="3" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="7" cy="3" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="8" cy="3" r="1" fill="rgba(63.9155%,62.3514%,62.3545%,1)"/>
+ <circle cx="9" cy="3" r="1" fill="rgba(64.0482%,62.3789%,62.3087%,1)"/>
+ <circle cx="10" cy="3" r="1" fill="rgba(63.9231%,62.3529%,62.3529%,1)"/>
+ <circle cx="11" cy="3" r="1" fill="rgba(60.0778%,61.5595%,63.6912%,1)"/>
+ <circle cx="12" cy="3" r="1" fill="rgba(52.5399%,60.0031%,66.3127%,1)"/>
+ <circle cx="13" cy="3" r="1" fill="rgba(52.2271%,59.939%,66.421%,1)"/>
+ <circle cx="14" cy="3" r="1" fill="rgba(63.5248%,62.2705%,62.4903%,1)"/>
+ <circle cx="15" cy="3" r="1" fill="rgba(63.9506%,62.359%,62.3423%,1)"/>
+ <circle cx="16" cy="3" r="1" fill="rgba(63.92%,62.3529%,62.3529%,1)"/>
+ <circle cx="17" cy="3" r="1" fill="rgba(64.1825%,62.4063%,62.2614%,1)"/>
+ <circle cx="18" cy="3" r="1" fill="rgba(59.8688%,61.5167%,63.7629%,1)"/>
+ <circle cx="19" cy="3" r="1" fill="rgba(49.6986%,59.4156%,67.2984%,1)"/>
+ <circle cx="20" cy="3" r="1" fill="rgba(56.1013%,60.737%,65.0721%,1)"/>
+ <circle cx="21" cy="3" r="1" fill="rgba(62.2797%,62.0142%,62.9236%,1)"/>
+ <circle cx="22" cy="3" r="1" fill="rgba(64.2267%,62.4155%,62.2461%,1)"/>
+ <circle cx="23" cy="3" r="1" fill="rgba(63.9307%,62.3545%,62.3499%,1)"/>
+ <circle cx="24" cy="3" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="25" cy="3" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="26" cy="3" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="27" cy="3" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="28" cy="3" r="1" fill="rgba(63.9155%,62.3468%,62.3468%,1)"/>
+ <circle cx="29" cy="3" r="1" fill="rgba(63.3097%,61.7136%,61.7136%,1)"/>
+ <circle cx="30" cy="3" r="1" fill="rgba(75.3201%,74.2473%,74.2473%,1)"/>
+ <circle cx="31" cy="3" r="1" fill="rgba(98.1582%,98.0774%,98.0774%,1)"/>
+ <circle cx="0" cy="4" r="1" fill="rgba(94.0902%,93.8338%,93.8338%,1)"/>
+ <circle cx="1" cy="4" r="1" fill="rgba(68.3284%,66.952%,66.952%,1)"/>
+ <circle cx="2" cy="4" r="1" fill="rgba(63.624%,62.0432%,62.0432%,1)"/>
+ <circle cx="3" cy="4" r="1" fill="rgba(63.9231%,62.3545%,62.3545%,1)"/>
+ <circle cx="4" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="5" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="6" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="7" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="8" cy="4" r="1" fill="rgba(64.0742%,62.385%,62.2995%,1)"/>
+ <circle cx="9" cy="4" r="1" fill="rgba(61.6526%,61.883%,63.1418%,1)"/>
+ <circle cx="10" cy="4" r="1" fill="rgba(44.9165%,58.4268%,68.9631%,1)"/>
+ <circle cx="11" cy="4" r="1" fill="rgba(33.312%,56.0311%,73.0007%,1)"/>
+ <circle cx="12" cy="4" r="1" fill="rgba(28.397%,55.0164%,74.7097%,1)"/>
+ <circle cx="13" cy="4" r="1" fill="rgba(31.1406%,55.5825%,73.7545%,1)"/>
+ <circle cx="14" cy="4" r="1" fill="rgba(56.8887%,60.8988%,64.799%,1)"/>
+ <circle cx="15" cy="4" r="1" fill="rgba(64.5869%,62.4903%,62.121%,1)"/>
+ <circle cx="16" cy="4" r="1" fill="rgba(64.2451%,62.4201%,62.24%,1)"/>
+ <circle cx="17" cy="4" r="1" fill="rgba(64.1703%,62.4048%,62.2675%,1)"/>
+ <circle cx="18" cy="4" r="1" fill="rgba(45.1087%,58.4695%,68.8975%,1)"/>
+ <circle cx="19" cy="4" r="1" fill="rgba(27.5746%,54.847%,74.995%,1)"/>
+ <circle cx="20" cy="4" r="1" fill="rgba(30.0328%,55.3536%,74.139%,1)"/>
+ <circle cx="21" cy="4" r="1" fill="rgba(37.0352%,56.8002%,71.7037%,1)"/>
+ <circle cx="22" cy="4" r="1" fill="rgba(52.9259%,60.0824%,66.1769%,1)"/>
+ <circle cx="23" cy="4" r="1" fill="rgba(64.033%,62.3758%,62.3133%,1)"/>
+ <circle cx="24" cy="4" r="1" fill="rgba(63.9261%,62.3545%,62.3514%,1)"/>
+ <circle cx="25" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="26" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="27" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="28" cy="4" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="29" cy="4" r="1" fill="rgba(63.8087%,62.2354%,62.2354%,1)"/>
+ <circle cx="30" cy="4" r="1" fill="rgba(65.6138%,64.1199%,64.1199%,1)"/>
+ <circle cx="31" cy="4" r="1" fill="rgba(89.1127%,88.6397%,88.6397%,1)"/>
+ <circle cx="0" cy="5" r="1" fill="rgba(87.0603%,86.4988%,86.4988%,1)"/>
+ <circle cx="1" cy="5" r="1" fill="rgba(64.7318%,63.1983%,63.1983%,1)"/>
+ <circle cx="2" cy="5" r="1" fill="rgba(63.8849%,62.3148%,62.3148%,1)"/>
+ <circle cx="3" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="4" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="5" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="6" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="7" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="8" cy="5" r="1" fill="rgba(64.2771%,62.4262%,62.2293%,1)"/>
+ <circle cx="9" cy="5" r="1" fill="rgba(58.4024%,61.2131%,64.2725%,1)"/>
+ <circle cx="10" cy="5" r="1" fill="rgba(30.7561%,55.5032%,73.8888%,1)"/>
+ <circle cx="11" cy="5" r="1" fill="rgba(27.277%,54.7845%,75.0988%,1)"/>
+ <circle cx="12" cy="5" r="1" fill="rgba(27.7897%,54.8913%,74.9203%,1)"/>
+ <circle cx="13" cy="5" r="1" fill="rgba(27.4037%,54.8104%,75.0546%,1)"/>
+ <circle cx="14" cy="5" r="1" fill="rgba(42.3804%,57.9034%,69.8451%,1)"/>
+ <circle cx="15" cy="5" r="1" fill="rgba(59.8184%,61.5045%,63.7797%,1)"/>
+ <circle cx="16" cy="5" r="1" fill="rgba(59.53%,61.4466%,63.8804%,1)"/>
+ <circle cx="17" cy="5" r="1" fill="rgba(55.9915%,60.7156%,65.1118%,1)"/>
+ <circle cx="18" cy="5" r="1" fill="rgba(32.3003%,55.8236%,73.3516%,1)"/>
+ <circle cx="19" cy="5" r="1" fill="rgba(27.538%,54.8394%,75.0088%,1)"/>
+ <circle cx="20" cy="5" r="1" fill="rgba(27.6982%,54.8714%,74.9523%,1)"/>
+ <circle cx="21" cy="5" r="1" fill="rgba(26.7277%,54.6715%,75.2895%,1)"/>
+ <circle cx="22" cy="5" r="1" fill="rgba(41.6068%,57.7447%,70.1152%,1)"/>
+ <circle cx="23" cy="5" r="1" fill="rgba(63.9902%,62.3667%,62.3285%,1)"/>
+ <circle cx="24" cy="5" r="1" fill="rgba(63.9292%,62.3545%,62.3499%,1)"/>
+ <circle cx="25" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="26" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="27" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="28" cy="5" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="29" cy="5" r="1" fill="rgba(63.9231%,62.3545%,62.3545%,1)"/>
+ <circle cx="30" cy="5" r="1" fill="rgba(63.7751%,62.2004%,62.2004%,1)"/>
+ <circle cx="31" cy="5" r="1" fill="rgba(80.5188%,79.6735%,79.6735%,1)"/>
+ <circle cx="0" cy="6" r="1" fill="rgba(84.1505%,83.4607%,83.4607%,1)"/>
+ <circle cx="1" cy="6" r="1" fill="rgba(64.1398%,62.5803%,62.5803%,1)"/>
+ <circle cx="2" cy="6" r="1" fill="rgba(63.9139%,62.3453%,62.3453%,1)"/>
+ <circle cx="3" cy="6" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="4" cy="6" r="1" fill="rgba(63.9292%,62.3545%,62.3499%,1)"/>
+ <circle cx="5" cy="6" r="1" fill="rgba(63.9414%,62.3575%,62.3453%,1)"/>
+ <circle cx="6" cy="6" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="7" cy="6" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="8" cy="6" r="1" fill="rgba(64.1917%,62.4079%,62.2599%,1)"/>
+ <circle cx="9" cy="6" r="1" fill="rgba(59.9573%,61.5335%,63.7308%,1)"/>
+ <circle cx="10" cy="6" r="1" fill="rgba(32.5353%,55.8709%,73.2692%,1)"/>
+ <circle cx="11" cy="6" r="1" fill="rgba(27.541%,54.8394%,75.0072%,1)"/>
+ <circle cx="12" cy="6" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="13" cy="6" r="1" fill="rgba(27.747%,54.8821%,74.9355%,1)"/>
+ <circle cx="14" cy="6" r="1" fill="rgba(29.1798%,55.1781%,74.4366%,1)"/>
+ <circle cx="15" cy="6" r="1" fill="rgba(32.2942%,55.8206%,73.3532%,1)"/>
+ <circle cx="16" cy="6" r="1" fill="rgba(31.9921%,55.758%,73.4585%,1)"/>
+ <circle cx="17" cy="6" r="1" fill="rgba(31.5404%,55.6649%,73.6156%,1)"/>
+ <circle cx="18" cy="6" r="1" fill="rgba(27.9637%,54.9264%,74.8608%,1)"/>
+ <circle cx="19" cy="6" r="1" fill="rgba(27.8355%,54.9004%,74.905%,1)"/>
+ <circle cx="20" cy="6" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="21" cy="6" r="1" fill="rgba(27.2587%,54.7814%,75.1049%,1)"/>
+ <circle cx="22" cy="6" r="1" fill="rgba(44.1566%,58.2712%,69.2271%,1)"/>
+ <circle cx="23" cy="6" r="1" fill="rgba(64.3381%,62.4384%,62.208%,1)"/>
+ <circle cx="24" cy="6" r="1" fill="rgba(63.9185%,62.3529%,62.3545%,1)"/>
+ <circle cx="25" cy="6" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="26" cy="6" r="1" fill="rgba(63.9261%,62.3545%,62.3514%,1)"/>
+ <circle cx="27" cy="6" r="1" fill="rgba(63.9445%,62.3575%,62.3453%,1)"/>
+ <circle cx="28" cy="6" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="29" cy="6" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="30" cy="6" r="1" fill="rgba(63.6118%,62.031%,62.031%,1)"/>
+ <circle cx="31" cy="6" r="1" fill="rgba(77.3739%,76.3897%,76.3897%,1)"/>
+ <circle cx="0" cy="7" r="1" fill="rgba(83.9826%,83.2868%,83.2868%,1)"/>
+ <circle cx="1" cy="7" r="1" fill="rgba(64.1215%,62.562%,62.562%,1)"/>
+ <circle cx="2" cy="7" r="1" fill="rgba(63.9139%,62.3453%,62.3453%,1)"/>
+ <circle cx="3" cy="7" r="1" fill="rgba(63.9368%,62.356%,62.3484%,1)"/>
+ <circle cx="4" cy="7" r="1" fill="rgba(64.0253%,62.3743%,62.3163%,1)"/>
+ <circle cx="5" cy="7" r="1" fill="rgba(63.8834%,62.3453%,62.3667%,1)"/>
+ <circle cx="6" cy="7" r="1" fill="rgba(64.2954%,62.4308%,62.2232%,1)"/>
+ <circle cx="7" cy="7" r="1" fill="rgba(63.9826%,62.3651%,62.3316%,1)"/>
+ <circle cx="8" cy="7" r="1" fill="rgba(64.4434%,62.4613%,62.1714%,1)"/>
+ <circle cx="9" cy="7" r="1" fill="rgba(58.0041%,61.1307%,64.4114%,1)"/>
+ <circle cx="10" cy="7" r="1" fill="rgba(32.5475%,55.874%,73.2647%,1)"/>
+ <circle cx="11" cy="7" r="1" fill="rgba(27.5395%,54.8394%,75.0072%,1)"/>
+ <circle cx="12" cy="7" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="13" cy="7" r="1" fill="rgba(27.8492%,54.9035%,74.9004%,1)"/>
+ <circle cx="14" cy="7" r="1" fill="rgba(27.7485%,54.8821%,74.9355%,1)"/>
+ <circle cx="15" cy="7" r="1" fill="rgba(27.5547%,54.8425%,75.0027%,1)"/>
+ <circle cx="16" cy="7" r="1" fill="rgba(27.5746%,54.847%,74.995%,1)"/>
+ <circle cx="17" cy="7" r="1" fill="rgba(27.6005%,54.8516%,74.9859%,1)"/>
+ <circle cx="18" cy="7" r="1" fill="rgba(27.8294%,54.8989%,74.9065%,1)"/>
+ <circle cx="19" cy="7" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="20" cy="7" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="21" cy="7" r="1" fill="rgba(27.4083%,54.8119%,75.053%,1)"/>
+ <circle cx="22" cy="7" r="1" fill="rgba(43.1098%,58.0545%,69.5918%,1)"/>
+ <circle cx="23" cy="7" r="1" fill="rgba(63.2868%,62.2217%,62.5727%,1)"/>
+ <circle cx="24" cy="7" r="1" fill="rgba(64.2115%,62.4125%,62.2522%,1)"/>
+ <circle cx="25" cy="7" r="1" fill="rgba(64.0497%,62.3789%,62.3087%,1)"/>
+ <circle cx="26" cy="7" r="1" fill="rgba(64.2679%,62.4247%,62.2324%,1)"/>
+ <circle cx="27" cy="7" r="1" fill="rgba(63.7995%,62.3285%,62.3941%,1)"/>
+ <circle cx="28" cy="7" r="1" fill="rgba(64.0497%,62.3789%,62.3087%,1)"/>
+ <circle cx="29" cy="7" r="1" fill="rgba(63.9139%,62.3514%,62.356%,1)"/>
+ <circle cx="30" cy="7" r="1" fill="rgba(63.6118%,62.0294%,62.0294%,1)"/>
+ <circle cx="31" cy="7" r="1" fill="rgba(77.2%,76.2097%,76.2097%,1)"/>
+ <circle cx="0" cy="8" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="8" r="1" fill="rgba(64.123%,62.5635%,62.5635%,1)"/>
+ <circle cx="2" cy="8" r="1" fill="rgba(63.9139%,62.3453%,62.3453%,1)"/>
+ <circle cx="3" cy="8" r="1" fill="rgba(64.3183%,62.4353%,62.2156%,1)"/>
+ <circle cx="4" cy="8" r="1" fill="rgba(54.4976%,60.4059%,65.6306%,1)"/>
+ <circle cx="5" cy="8" r="1" fill="rgba(43.093%,58.0514%,69.5964%,1)"/>
+ <circle cx="6" cy="8" r="1" fill="rgba(56.6781%,60.8576%,64.8707%,1)"/>
+ <circle cx="7" cy="8" r="1" fill="rgba(63.5706%,62.2797%,62.475%,1)"/>
+ <circle cx="8" cy="8" r="1" fill="rgba(53.4112%,60.1831%,66.0105%,1)"/>
+ <circle cx="9" cy="8" r="1" fill="rgba(34.8653%,56.3531%,72.4605%,1)"/>
+ <circle cx="10" cy="8" r="1" fill="rgba(28.0003%,54.934%,74.847%,1)"/>
+ <circle cx="11" cy="8" r="1" fill="rgba(27.8218%,54.8974%,74.9096%,1)"/>
+ <circle cx="12" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="13" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="14" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="15" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="16" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="18" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="19" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="20" cy="8" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="21" cy="8" r="1" fill="rgba(27.7638%,54.8852%,74.9294%,1)"/>
+ <circle cx="22" cy="8" r="1" fill="rgba(29.3889%,55.2209%,74.3648%,1)"/>
+ <circle cx="23" cy="8" r="1" fill="rgba(42.1057%,57.847%,69.9428%,1)"/>
+ <circle cx="24" cy="8" r="1" fill="rgba(60.0214%,61.5488%,63.711%,1)"/>
+ <circle cx="25" cy="8" r="1" fill="rgba(62.3774%,62.034%,62.8901%,1)"/>
+ <circle cx="26" cy="8" r="1" fill="rgba(50.1381%,59.5071%,67.1458%,1)"/>
+ <circle cx="27" cy="8" r="1" fill="rgba(44.358%,58.3124%,69.1569%,1)"/>
+ <circle cx="28" cy="8" r="1" fill="rgba(61.4038%,61.8341%,63.2288%,1)"/>
+ <circle cx="29" cy="8" r="1" fill="rgba(64.1459%,62.3987%,62.2751%,1)"/>
+ <circle cx="30" cy="8" r="1" fill="rgba(63.6072%,62.0294%,62.031%,1)"/>
+ <circle cx="31" cy="8" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="9" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="9" r="1" fill="rgba(64.1184%,62.562%,62.565%,1)"/>
+ <circle cx="2" cy="9" r="1" fill="rgba(64.2924%,62.4231%,62.2141%,1)"/>
+ <circle cx="3" cy="9" r="1" fill="rgba(58.0743%,61.146%,64.387%,1)"/>
+ <circle cx="4" cy="9" r="1" fill="rgba(33.9574%,56.1654%,72.7749%,1)"/>
+ <circle cx="5" cy="9" r="1" fill="rgba(27.0375%,54.7356%,75.1812%,1)"/>
+ <circle cx="6" cy="9" r="1" fill="rgba(31.8013%,55.7183%,73.5241%,1)"/>
+ <circle cx="7" cy="9" r="1" fill="rgba(40.5859%,57.5326%,70.4677%,1)"/>
+ <circle cx="8" cy="9" r="1" fill="rgba(30.8248%,55.5169%,73.8643%,1)"/>
+ <circle cx="9" cy="9" r="1" fill="rgba(27.3732%,54.8043%,75.0652%,1)"/>
+ <circle cx="10" cy="9" r="1" fill="rgba(27.8279%,54.8989%,74.9081%,1)"/>
+ <circle cx="11" cy="9" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="12" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="13" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="14" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="15" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="16" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="18" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="19" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="20" cy="9" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="21" cy="9" r="1" fill="rgba(27.8477%,54.9035%,74.9004%,1)"/>
+ <circle cx="22" cy="9" r="1" fill="rgba(27.7104%,54.8745%,74.9477%,1)"/>
+ <circle cx="23" cy="9" r="1" fill="rgba(27.5364%,54.8379%,75.0088%,1)"/>
+ <circle cx="24" cy="9" r="1" fill="rgba(36.0464%,56.5972%,72.05%,1)"/>
+ <circle cx="25" cy="9" r="1" fill="rgba(38.3337%,57.0687%,71.2535%,1)"/>
+ <circle cx="26" cy="9" r="1" fill="rgba(28.5618%,55.05%,74.6517%,1)"/>
+ <circle cx="27" cy="9" r="1" fill="rgba(27.6051%,54.8531%,74.9844%,1)"/>
+ <circle cx="28" cy="9" r="1" fill="rgba(44.1382%,58.2681%,69.2332%,1)"/>
+ <circle cx="29" cy="9" r="1" fill="rgba(63.2853%,62.2217%,62.5742%,1)"/>
+ <circle cx="30" cy="9" r="1" fill="rgba(63.6927%,62.0462%,62.002%,1)"/>
+ <circle cx="31" cy="9" r="1" fill="rgba(77.2137%,76.2219%,76.2234%,1)"/>
+ <circle cx="0" cy="10" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="10" r="1" fill="rgba(64.2542%,62.591%,62.5177%,1)"/>
+ <circle cx="2" cy="10" r="1" fill="rgba(61.9684%,61.944%,63.0228%,1)"/>
+ <circle cx="3" cy="10" r="1" fill="rgba(39.4156%,57.293%,70.8766%,1)"/>
+ <circle cx="4" cy="10" r="1" fill="rgba(27.3579%,54.8013%,75.0713%,1)"/>
+ <circle cx="5" cy="10" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="6" cy="10" r="1" fill="rgba(27.6158%,54.8547%,74.9813%,1)"/>
+ <circle cx="7" cy="10" r="1" fill="rgba(27.3198%,54.7936%,75.0835%,1)"/>
+ <circle cx="8" cy="10" r="1" fill="rgba(27.6753%,54.8669%,74.9599%,1)"/>
+ <circle cx="9" cy="10" r="1" fill="rgba(27.8508%,54.9035%,74.8989%,1)"/>
+ <circle cx="10" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="11" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="12" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="13" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="14" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="15" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="16" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="18" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="19" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="20" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="21" cy="10" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="22" cy="10" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="23" cy="10" r="1" fill="rgba(27.8294%,54.8989%,74.9065%,1)"/>
+ <circle cx="24" cy="10" r="1" fill="rgba(27.4815%,54.8272%,75.0286%,1)"/>
+ <circle cx="25" cy="10" r="1" fill="rgba(27.3777%,54.8058%,75.0637%,1)"/>
+ <circle cx="26" cy="10" r="1" fill="rgba(27.7745%,54.8882%,74.9264%,1)"/>
+ <circle cx="27" cy="10" r="1" fill="rgba(27.6905%,54.8699%,74.9554%,1)"/>
+ <circle cx="28" cy="10" r="1" fill="rgba(29.1783%,55.1781%,74.4366%,1)"/>
+ <circle cx="29" cy="10" r="1" fill="rgba(51.107%,59.707%,66.8101%,1)"/>
+ <circle cx="30" cy="10" r="1" fill="rgba(63.8773%,62.0844%,61.9379%,1)"/>
+ <circle cx="31" cy="10" r="1" fill="rgba(77.2213%,76.2249%,76.2203%,1)"/>
+ <circle cx="0" cy="11" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="11" r="1" fill="rgba(64.4862%,62.6383%,62.4384%,1)"/>
+ <circle cx="2" cy="11" r="1" fill="rgba(57.8683%,61.0971%,64.448%,1)"/>
+ <circle cx="3" cy="11" r="1" fill="rgba(31.2123%,55.5978%,73.7301%,1)"/>
+ <circle cx="4" cy="11" r="1" fill="rgba(27.5608%,54.844%,74.9996%,1)"/>
+ <circle cx="5" cy="11" r="1" fill="rgba(27.8462%,54.902%,74.9004%,1)"/>
+ <circle cx="6" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="7" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="8" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="9" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="10" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="11" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="12" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="13" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="14" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="15" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="16" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="18" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="19" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="20" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="21" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="22" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="23" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="24" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="25" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="26" cy="11" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="27" cy="11" r="1" fill="rgba(27.8538%,54.9035%,74.8989%,1)"/>
+ <circle cx="28" cy="11" r="1" fill="rgba(27.1351%,54.7555%,75.1476%,1)"/>
+ <circle cx="29" cy="11" r="1" fill="rgba(41.6251%,57.7493%,70.1091%,1)"/>
+ <circle cx="30" cy="11" r="1" fill="rgba(63.3539%,61.976%,62.1195%,1)"/>
+ <circle cx="31" cy="11" r="1" fill="rgba(77.2473%,76.2295%,76.2112%,1)"/>
+ <circle cx="0" cy="12" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="12" r="1" fill="rgba(64.1672%,62.5727%,62.5483%,1)"/>
+ <circle cx="2" cy="12" r="1" fill="rgba(63.5431%,62.269%,62.475%,1)"/>
+ <circle cx="3" cy="12" r="1" fill="rgba(45.1118%,58.4695%,68.896%,1)"/>
+ <circle cx="4" cy="12" r="1" fill="rgba(27.8965%,54.9126%,74.8836%,1)"/>
+ <circle cx="5" cy="12" r="1" fill="rgba(27.8141%,54.8959%,74.9126%,1)"/>
+ <circle cx="6" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="7" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="8" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="9" cy="12" r="1" fill="rgba(27.7699%,54.8562%,74.876%,1)"/>
+ <circle cx="10" cy="12" r="1" fill="rgba(27.7226%,54.8272%,74.8608%,1)"/>
+ <circle cx="11" cy="12" r="1" fill="rgba(27.8309%,54.8943%,74.8974%,1)"/>
+ <circle cx="12" cy="12" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="13" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="14" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="15" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="16" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="18" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="19" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="20" cy="12" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="21" cy="12" r="1" fill="rgba(27.8233%,54.8898%,74.8943%,1)"/>
+ <circle cx="22" cy="12" r="1" fill="rgba(27.715%,54.8226%,74.8577%,1)"/>
+ <circle cx="23" cy="12" r="1" fill="rgba(27.7836%,54.8653%,74.8806%,1)"/>
+ <circle cx="24" cy="12" r="1" fill="rgba(27.8447%,54.9035%,74.902%,1)"/>
+ <circle cx="25" cy="12" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="26" cy="12" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="27" cy="12" r="1" fill="rgba(27.5837%,54.8486%,74.992%,1)"/>
+ <circle cx="28" cy="12" r="1" fill="rgba(31.8257%,55.7259%,73.518%,1)"/>
+ <circle cx="29" cy="12" r="1" fill="rgba(56.1975%,60.7599%,65.0416%,1)"/>
+ <circle cx="30" cy="12" r="1" fill="rgba(63.9475%,62.0996%,61.912%,1)"/>
+ <circle cx="31" cy="12" r="1" fill="rgba(77.2137%,76.2234%,76.2219%,1)"/>
+ <circle cx="0" cy="13" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="13" r="1" fill="rgba(64.1215%,62.5635%,62.565%,1)"/>
+ <circle cx="2" cy="13" r="1" fill="rgba(64.1428%,62.3926%,62.266%,1)"/>
+ <circle cx="3" cy="13" r="1" fill="rgba(61.0788%,61.767%,63.3417%,1)"/>
+ <circle cx="4" cy="13" r="1" fill="rgba(36.35%,56.6598%,71.9417%,1)"/>
+ <circle cx="5" cy="13" r="1" fill="rgba(27.4098%,54.8119%,75.053%,1)"/>
+ <circle cx="6" cy="13" r="1" fill="rgba(27.8447%,54.9035%,74.902%,1)"/>
+ <circle cx="7" cy="13" r="1" fill="rgba(27.8126%,54.8821%,74.8913%,1)"/>
+ <circle cx="8" cy="13" r="1" fill="rgba(27.1183%,54.4488%,74.6487%,1)"/>
+ <circle cx="9" cy="13" r="1" fill="rgba(28.7739%,55.4894%,75.2361%,1)"/>
+ <circle cx="10" cy="13" r="1" fill="rgba(29.8528%,56.1852%,75.6481%,1)"/>
+ <circle cx="11" cy="13" r="1" fill="rgba(27.3213%,54.58%,74.728%,1)"/>
+ <circle cx="12" cy="13" r="1" fill="rgba(27.5837%,54.7387%,74.8104%,1)"/>
+ <circle cx="13" cy="13" r="1" fill="rgba(27.8569%,54.9096%,74.9065%,1)"/>
+ <circle cx="14" cy="13" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="15" cy="13" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="16" cy="13" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="13" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="18" cy="13" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="19" cy="13" r="1" fill="rgba(27.8599%,54.9126%,74.9081%,1)"/>
+ <circle cx="20" cy="13" r="1" fill="rgba(27.4922%,54.6822%,74.7784%,1)"/>
+ <circle cx="21" cy="13" r="1" fill="rgba(27.4998%,54.6929%,74.7936%,1)"/>
+ <circle cx="22" cy="13" r="1" fill="rgba(30.0084%,56.2829%,75.7015%,1)"/>
+ <circle cx="23" cy="13" r="1" fill="rgba(28.4535%,55.288%,75.1217%,1)"/>
+ <circle cx="24" cy="13" r="1" fill="rgba(27.1687%,54.4793%,74.667%,1)"/>
+ <circle cx="25" cy="13" r="1" fill="rgba(27.8386%,54.8989%,74.9004%,1)"/>
+ <circle cx="26" cy="13" r="1" fill="rgba(27.8111%,54.8959%,74.9142%,1)"/>
+ <circle cx="27" cy="13" r="1" fill="rgba(28.1178%,54.9584%,74.8058%,1)"/>
+ <circle cx="28" cy="13" r="1" fill="rgba(48.1849%,59.1043%,67.8264%,1)"/>
+ <circle cx="29" cy="13" r="1" fill="rgba(64.2191%,62.414%,62.2492%,1)"/>
+ <circle cx="30" cy="13" r="1" fill="rgba(63.6271%,62.0325%,62.0233%,1)"/>
+ <circle cx="31" cy="13" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="14" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="14" r="1" fill="rgba(64.123%,62.5635%,62.5635%,1)"/>
+ <circle cx="2" cy="14" r="1" fill="rgba(63.9139%,62.3453%,62.3453%,1)"/>
+ <circle cx="3" cy="14" r="1" fill="rgba(64.1398%,62.3987%,62.2766%,1)"/>
+ <circle cx="4" cy="14" r="1" fill="rgba(42.1439%,57.8546%,69.9229%,1)"/>
+ <circle cx="5" cy="14" r="1" fill="rgba(27.2068%,54.7707%,75.1232%,1)"/>
+ <circle cx="6" cy="14" r="1" fill="rgba(27.8233%,54.8898%,74.8943%,1)"/>
+ <circle cx="7" cy="14" r="1" fill="rgba(27.6844%,54.7997%,74.8409%,1)"/>
+ <circle cx="8" cy="14" r="1" fill="rgba(46.2409%,66.4668%,81.416%,1)"/>
+ <circle cx="9" cy="14" r="1" fill="rgba(75.7458%,84.9928%,91.8227%,1)"/>
+ <circle cx="10" cy="14" r="1" fill="rgba(79.2706%,86.6392%,92.1019%,1)"/>
+ <circle cx="11" cy="14" r="1" fill="rgba(60.3326%,75.3948%,86.5232%,1)"/>
+ <circle cx="12" cy="14" r="1" fill="rgba(31.3344%,57.1313%,76.1959%,1)"/>
+ <circle cx="13" cy="14" r="1" fill="rgba(27.5731%,54.7311%,74.8043%,1)"/>
+ <circle cx="14" cy="14" r="1" fill="rgba(27.8584%,54.9111%,74.9081%,1)"/>
+ <circle cx="15" cy="14" r="1" fill="rgba(27.5731%,54.7326%,74.8089%,1)"/>
+ <circle cx="16" cy="14" r="1" fill="rgba(26.8971%,54.3114%,74.5724%,1)"/>
+ <circle cx="17" cy="14" r="1" fill="rgba(27.6524%,54.7829%,74.8363%,1)"/>
+ <circle cx="18" cy="14" r="1" fill="rgba(27.8569%,54.9111%,74.9065%,1)"/>
+ <circle cx="19" cy="14" r="1" fill="rgba(27.4693%,54.6639%,74.7646%,1)"/>
+ <circle cx="20" cy="14" r="1" fill="rgba(33.1945%,58.32%,76.8872%,1)"/>
+ <circle cx="21" cy="14" r="1" fill="rgba(63.5966%,77.3907%,87.5822%,1)"/>
+ <circle cx="22" cy="14" r="1" fill="rgba(79.881%,87.0237%,92.3201%,1)"/>
+ <circle cx="23" cy="14" r="1" fill="rgba(73.7942%,83.8163%,91.2154%,1)"/>
+ <circle cx="24" cy="14" r="1" fill="rgba(42.7893%,64.2863%,80.174%,1)"/>
+ <circle cx="25" cy="14" r="1" fill="rgba(27.4311%,54.6426%,74.7555%,1)"/>
+ <circle cx="26" cy="14" r="1" fill="rgba(27.7577%,54.8836%,74.931%,1)"/>
+ <circle cx="27" cy="14" r="1" fill="rgba(29.2332%,55.1888%,74.4167%,1)"/>
+ <circle cx="28" cy="14" r="1" fill="rgba(55.2972%,60.5707%,65.3468%,1)"/>
+ <circle cx="29" cy="14" r="1" fill="rgba(64.4755%,62.4674%,62.1607%,1)"/>
+ <circle cx="30" cy="14" r="1" fill="rgba(63.6103%,62.0294%,62.0294%,1)"/>
+ <circle cx="31" cy="14" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="15" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="15" r="1" fill="rgba(64.123%,62.5635%,62.5635%,1)"/>
+ <circle cx="2" cy="15" r="1" fill="rgba(63.9216%,62.3468%,62.3438%,1)"/>
+ <circle cx="3" cy="15" r="1" fill="rgba(64.0162%,62.3728%,62.3194%,1)"/>
+ <circle cx="4" cy="15" r="1" fill="rgba(42.0249%,57.8302%,69.9641%,1)"/>
+ <circle cx="5" cy="15" r="1" fill="rgba(27.2145%,54.7723%,75.1202%,1)"/>
+ <circle cx="6" cy="15" r="1" fill="rgba(27.1321%,54.4579%,74.6548%,1)"/>
+ <circle cx="7" cy="15" r="1" fill="rgba(40.5112%,62.8794%,79.4095%,1)"/>
+ <circle cx="8" cy="15" r="1" fill="rgba(88.3421%,91.8837%,94.5296%,1)"/>
+ <circle cx="9" cy="15" r="1" fill="rgba(69.34%,68.5878%,68.4962%,1)"/>
+ <circle cx="10" cy="15" r="1" fill="rgba(49.5277%,48.7846%,48.983%,1)"/>
+ <circle cx="11" cy="15" r="1" fill="rgba(70.7088%,70.6935%,71.0994%,1)"/>
+ <circle cx="12" cy="15" r="1" fill="rgba(59.8657%,74.4808%,85.2995%,1)"/>
+ <circle cx="13" cy="15" r="1" fill="rgba(27.5792%,54.7738%,74.873%,1)"/>
+ <circle cx="14" cy="15" r="1" fill="rgba(27.5868%,54.7417%,74.8119%,1)"/>
+ <circle cx="15" cy="15" r="1" fill="rgba(32.2637%,57.6654%,76.4401%,1)"/>
+ <circle cx="16" cy="15" r="1" fill="rgba(43.9353%,64.9607%,80.5005%,1)"/>
+ <circle cx="17" cy="15" r="1" fill="rgba(30.9255%,56.8292%,75.9747%,1)"/>
+ <circle cx="18" cy="15" r="1" fill="rgba(27.6005%,54.7509%,74.818%,1)"/>
+ <circle cx="19" cy="15" r="1" fill="rgba(28.4733%,55.3597%,75.2316%,1)"/>
+ <circle cx="20" cy="15" r="1" fill="rgba(64.7044%,77.0443%,86.1997%,1)"/>
+ <circle cx="21" cy="15" r="1" fill="rgba(67.7058%,67.3045%,67.4815%,1)"/>
+ <circle cx="22" cy="15" r="1" fill="rgba(49.5399%,48.8151%,49.0227%,1)"/>
+ <circle cx="23" cy="15" r="1" fill="rgba(73.4035%,72.6528%,72.5048%,1)"/>
+ <circle cx="24" cy="15" r="1" fill="rgba(85.449%,90.5135%,94.2702%,1)"/>
+ <circle cx="25" cy="15" r="1" fill="rgba(36.5072%,60.351%,77.9736%,1)"/>
+ <circle cx="26" cy="15" r="1" fill="rgba(27.2267%,54.5525%,74.7463%,1)"/>
+ <circle cx="27" cy="15" r="1" fill="rgba(29.2271%,55.1873%,74.4182%,1)"/>
+ <circle cx="28" cy="15" r="1" fill="rgba(55.1003%,60.531%,65.4154%,1)"/>
+ <circle cx="29" cy="15" r="1" fill="rgba(64.448%,62.4613%,62.1698%,1)"/>
+ <circle cx="30" cy="15" r="1" fill="rgba(63.6118%,62.0294%,62.0294%,1)"/>
+ <circle cx="31" cy="15" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="16" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="16" r="1" fill="rgba(64.123%,62.5635%,62.5635%,1)"/>
+ <circle cx="2" cy="16" r="1" fill="rgba(63.9216%,62.3468%,62.3438%,1)"/>
+ <circle cx="3" cy="16" r="1" fill="rgba(64.0146%,62.3728%,62.3194%,1)"/>
+ <circle cx="4" cy="16" r="1" fill="rgba(42.0233%,57.8302%,69.9641%,1)"/>
+ <circle cx="5" cy="16" r="1" fill="rgba(27.2145%,54.7723%,75.1202%,1)"/>
+ <circle cx="6" cy="16" r="1" fill="rgba(26.6407%,54.1497%,74.4839%,1)"/>
+ <circle cx="7" cy="16" r="1" fill="rgba(58.6587%,74.5525%,86.2852%,1)"/>
+ <circle cx="8" cy="16" r="1" fill="rgba(82.0249%,81.8204%,81.9333%,1)"/>
+ <circle cx="9" cy="16" r="1" fill="rgba(28.7587%,28.3772%,29.1234%,1)"/>
+ <circle cx="10" cy="16" r="1" fill="rgba(23.592%,23.1922%,23.9963%,1)"/>
+ <circle cx="11" cy="16" r="1" fill="rgba(32.3705%,31.5923%,32.0089%,1)"/>
+ <circle cx="12" cy="16" r="1" fill="rgba(68.4504%,74.9844%,80.0137%,1)"/>
+ <circle cx="13" cy="16" r="1" fill="rgba(31.5969%,57.5708%,76.7575%,1)"/>
+ <circle cx="14" cy="16" r="1" fill="rgba(26.5156%,54.0719%,74.4396%,1)"/>
+ <circle cx="15" cy="16" r="1" fill="rgba(54.0719%,71.2963%,84.0253%,1)"/>
+ <circle cx="16" cy="16" r="1" fill="rgba(95.3033%,97.0657%,98.3658%,1)"/>
+ <circle cx="17" cy="16" r="1" fill="rgba(48.0766%,67.5502%,81.9394%,1)"/>
+ <circle cx="18" cy="16" r="1" fill="rgba(26.389%,53.9925%,74.3969%,1)"/>
+ <circle cx="19" cy="16" r="1" fill="rgba(34.6792%,59.5789%,77.966%,1)"/>
+ <circle cx="20" cy="16" r="1" fill="rgba(68.3268%,72.8725%,76.5118%,1)"/>
+ <circle cx="21" cy="16" r="1" fill="rgba(29.1096%,28.4154%,28.9357%,1)"/>
+ <circle cx="22" cy="16" r="1" fill="rgba(23.5828%,23.1815%,23.9872%,1)"/>
+ <circle cx="23" cy="16" r="1" fill="rgba(31.9966%,31.6136%,32.311%,1)"/>
+ <circle cx="24" cy="16" r="1" fill="rgba(86.0166%,86.3157%,86.7231%,1)"/>
+ <circle cx="25" cy="16" r="1" fill="rgba(52.0287%,70.3227%,83.8331%,1)"/>
+ <circle cx="26" cy="16" r="1" fill="rgba(26.5553%,54.1329%,74.5129%,1)"/>
+ <circle cx="27" cy="16" r="1" fill="rgba(29.2271%,55.1873%,74.4182%,1)"/>
+ <circle cx="28" cy="16" r="1" fill="rgba(55.0988%,60.5295%,65.417%,1)"/>
+ <circle cx="29" cy="16" r="1" fill="rgba(64.448%,62.4613%,62.1698%,1)"/>
+ <circle cx="30" cy="16" r="1" fill="rgba(63.6118%,62.0294%,62.0294%,1)"/>
+ <circle cx="31" cy="16" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="17" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="17" r="1" fill="rgba(64.123%,62.5635%,62.5635%,1)"/>
+ <circle cx="2" cy="17" r="1" fill="rgba(63.9216%,62.3468%,62.3438%,1)"/>
+ <circle cx="3" cy="17" r="1" fill="rgba(64.0146%,62.3728%,62.3194%,1)"/>
+ <circle cx="4" cy="17" r="1" fill="rgba(42.0233%,57.8302%,69.9641%,1)"/>
+ <circle cx="5" cy="17" r="1" fill="rgba(27.2145%,54.7723%,75.1202%,1)"/>
+ <circle cx="6" cy="17" r="1" fill="rgba(26.6819%,54.1756%,74.4976%,1)"/>
+ <circle cx="7" cy="17" r="1" fill="rgba(55.0256%,72.2835%,85.0233%,1)"/>
+ <circle cx="8" cy="17" r="1" fill="rgba(81.0712%,81.2039%,81.5656%,1)"/>
+ <circle cx="9" cy="17" r="1" fill="rgba(28.8075%,28.3894%,29.1081%,1)"/>
+ <circle cx="10" cy="17" r="1" fill="rgba(23.5996%,23.1998%,24.007%,1)"/>
+ <circle cx="11" cy="17" r="1" fill="rgba(32.6299%,31.7327%,32.0607%,1)"/>
+ <circle cx="12" cy="17" r="1" fill="rgba(64.9485%,72.7764%,78.764%,1)"/>
+ <circle cx="13" cy="17" r="1" fill="rgba(30.6035%,56.9512%,76.4126%,1)"/>
+ <circle cx="14" cy="17" r="1" fill="rgba(26.4805%,54.0505%,74.4274%,1)"/>
+ <circle cx="15" cy="17" r="1" fill="rgba(58.0621%,73.7911%,85.4124%,1)"/>
+ <circle cx="16" cy="17" r="1" fill="rgba(99.7101%,99.8199%,99.8993%,1)"/>
+ <circle cx="17" cy="17" r="1" fill="rgba(51.6182%,69.7658%,83.1693%,1)"/>
+ <circle cx="18" cy="17" r="1" fill="rgba(26.3325%,53.9574%,74.3771%,1)"/>
+ <circle cx="19" cy="17" r="1" fill="rgba(33.2082%,58.6603%,77.4563%,1)"/>
+ <circle cx="20" cy="17" r="1" fill="rgba(65.2277%,70.9148%,75.3964%,1)"/>
+ <circle cx="21" cy="17" r="1" fill="rgba(29.4209%,28.5924%,29.0135%,1)"/>
+ <circle cx="22" cy="17" r="1" fill="rgba(23.5859%,23.1876%,23.9948%,1)"/>
+ <circle cx="23" cy="17" r="1" fill="rgba(32.0897%,31.6487%,32.3049%,1)"/>
+ <circle cx="24" cy="17" r="1" fill="rgba(84.5853%,85.4032%,86.1967%,1)"/>
+ <circle cx="25" cy="17" r="1" fill="rgba(48.751%,68.275%,82.6947%,1)"/>
+ <circle cx="26" cy="17" r="1" fill="rgba(26.6743%,54.2061%,74.5541%,1)"/>
+ <circle cx="27" cy="17" r="1" fill="rgba(29.2271%,55.1873%,74.4182%,1)"/>
+ <circle cx="28" cy="17" r="1" fill="rgba(55.0988%,60.5295%,65.417%,1)"/>
+ <circle cx="29" cy="17" r="1" fill="rgba(64.448%,62.4613%,62.1698%,1)"/>
+ <circle cx="30" cy="17" r="1" fill="rgba(63.6118%,62.0294%,62.0294%,1)"/>
+ <circle cx="31" cy="17" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="18" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="18" r="1" fill="rgba(64.123%,62.5635%,62.5635%,1)"/>
+ <circle cx="2" cy="18" r="1" fill="rgba(63.9216%,62.3468%,62.3438%,1)"/>
+ <circle cx="3" cy="18" r="1" fill="rgba(64.0131%,62.3713%,62.3178%,1)"/>
+ <circle cx="4" cy="18" r="1" fill="rgba(42.0005%,57.8134%,69.9535%,1)"/>
+ <circle cx="5" cy="18" r="1" fill="rgba(27.2114%,54.7707%,75.1202%,1)"/>
+ <circle cx="6" cy="18" r="1" fill="rgba(27.4296%,54.6441%,74.7585%,1)"/>
+ <circle cx="7" cy="18" r="1" fill="rgba(34.4823%,59.1119%,77.3129%,1)"/>
+ <circle cx="8" cy="18" r="1" fill="rgba(77.525%,85.1392%,90.7973%,1)"/>
+ <circle cx="9" cy="18" r="1" fill="rgba(67.8889%,67.6158%,67.8828%,1)"/>
+ <circle cx="10" cy="18" r="1" fill="rgba(49.0242%,48.3696%,48.6351%,1)"/>
+ <circle cx="11" cy="18" r="1" fill="rgba(64.2329%,66.5797%,68.7312%,1)"/>
+ <circle cx="12" cy="18" r="1" fill="rgba(48.7907%,67.5486%,81.4298%,1)"/>
+ <circle cx="13" cy="18" r="1" fill="rgba(27.2511%,54.5693%,74.7585%,1)"/>
+ <circle cx="14" cy="18" r="1" fill="rgba(26.6056%,54.1283%,74.4717%,1)"/>
+ <circle cx="15" cy="18" r="1" fill="rgba(57.8286%,73.6461%,85.3315%,1)"/>
+ <circle cx="16" cy="18" r="1" fill="rgba(99.6002%,99.7513%,99.8596%,1)"/>
+ <circle cx="17" cy="18" r="1" fill="rgba(51.3695%,69.6101%,83.0838%,1)"/>
+ <circle cx="18" cy="18" r="1" fill="rgba(26.6011%,54.1253%,74.4701%,1)"/>
+ <circle cx="19" cy="18" r="1" fill="rgba(27.5975%,54.8135%,74.9279%,1)"/>
+ <circle cx="20" cy="18" r="1" fill="rgba(52.8313%,69.6086%,82.0432%,1)"/>
+ <circle cx="21" cy="18" r="1" fill="rgba(62.4216%,63.9307%,65.5222%,1)"/>
+ <circle cx="22" cy="18" r="1" fill="rgba(49.1325%,48.4596%,48.7083%,1)"/>
+ <circle cx="23" cy="18" r="1" fill="rgba(71.4397%,71.3771%,71.7372%,1)"/>
+ <circle cx="24" cy="18" r="1" fill="rgba(73.817%,83.2609%,90.2541%,1)"/>
+ <circle cx="25" cy="18" r="1" fill="rgba(31.8822%,57.4594%,76.3638%,1)"/>
+ <circle cx="26" cy="18" r="1" fill="rgba(27.4861%,54.7143%,74.8363%,1)"/>
+ <circle cx="27" cy="18" r="1" fill="rgba(29.2241%,55.1858%,74.4182%,1)"/>
+ <circle cx="28" cy="18" r="1" fill="rgba(55.0958%,60.528%,65.4139%,1)"/>
+ <circle cx="29" cy="18" r="1" fill="rgba(64.448%,62.4613%,62.1698%,1)"/>
+ <circle cx="30" cy="18" r="1" fill="rgba(63.6118%,62.0294%,62.0294%,1)"/>
+ <circle cx="31" cy="18" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="19" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="19" r="1" fill="rgba(64.1215%,62.5635%,62.565%,1)"/>
+ <circle cx="2" cy="19" r="1" fill="rgba(63.9582%,62.3545%,62.3316%,1)"/>
+ <circle cx="3" cy="19" r="1" fill="rgba(64.4831%,62.4811%,62.179%,1)"/>
+ <circle cx="4" cy="19" r="1" fill="rgba(42.4613%,58.0468%,70.0237%,1)"/>
+ <circle cx="5" cy="19" r="1" fill="rgba(26.7903%,54.5113%,74.9798%,1)"/>
+ <circle cx="6" cy="19" r="1" fill="rgba(27.8614%,54.9142%,74.9081%,1)"/>
+ <circle cx="7" cy="19" r="1" fill="rgba(27.0756%,54.4182%,74.6288%,1)"/>
+ <circle cx="8" cy="19" r="1" fill="rgba(34.725%,59.2706%,77.4121%,1)"/>
+ <circle cx="9" cy="19" r="1" fill="rgba(56.6278%,73.0358%,85.1606%,1)"/>
+ <circle cx="10" cy="19" r="1" fill="rgba(60.2289%,74.7097%,85.4292%,1)"/>
+ <circle cx="11" cy="19" r="1" fill="rgba(43.9994%,65.182%,80.8331%,1)"/>
+ <circle cx="12" cy="19" r="1" fill="rgba(28.2094%,55.1781%,75.1095%,1)"/>
+ <circle cx="13" cy="19" r="1" fill="rgba(27.7699%,54.8547%,74.873%,1)"/>
+ <circle cx="14" cy="19" r="1" fill="rgba(27.1183%,54.4488%,74.6502%,1)"/>
+ <circle cx="15" cy="19" r="1" fill="rgba(42.9984%,64.3748%,80.174%,1)"/>
+ <circle cx="16" cy="19" r="1" fill="rgba(72.4804%,82.8%,90.428%,1)"/>
+ <circle cx="17" cy="19" r="1" fill="rgba(39.1318%,61.9577%,78.8281%,1)"/>
+ <circle cx="18" cy="19" r="1" fill="rgba(27.2145%,54.5098%,74.6838%,1)"/>
+ <circle cx="19" cy="19" r="1" fill="rgba(27.7089%,54.8135%,74.8486%,1)"/>
+ <circle cx="20" cy="19" r="1" fill="rgba(28.8792%,55.6222%,75.3872%,1)"/>
+ <circle cx="21" cy="19" r="1" fill="rgba(46.3523%,66.6056%,81.5702%,1)"/>
+ <circle cx="22" cy="19" r="1" fill="rgba(60.8972%,75.1293%,85.6657%,1)"/>
+ <circle cx="23" cy="19" r="1" fill="rgba(54.7982%,71.9402%,84.6021%,1)"/>
+ <circle cx="24" cy="19" r="1" fill="rgba(32.8054%,58.0468%,76.701%,1)"/>
+ <circle cx="25" cy="19" r="1" fill="rgba(27.1824%,54.4869%,74.6685%,1)"/>
+ <circle cx="26" cy="19" r="1" fill="rgba(27.7592%,54.8852%,74.9325%,1)"/>
+ <circle cx="27" cy="19" r="1" fill="rgba(28.7343%,54.8745%,74.2397%,1)"/>
+ <circle cx="28" cy="19" r="1" fill="rgba(55.2453%,60.4791%,65.2308%,1)"/>
+ <circle cx="29" cy="19" r="1" fill="rgba(64.6891%,62.5116%,62.0874%,1)"/>
+ <circle cx="30" cy="19" r="1" fill="rgba(63.6027%,62.0279%,62.0325%,1)"/>
+ <circle cx="31" cy="19" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="20" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="20" r="1" fill="rgba(64.1642%,62.5727%,62.5498%,1)"/>
+ <circle cx="2" cy="20" r="1" fill="rgba(63.093%,62.1225%,62.5422%,1)"/>
+ <circle cx="3" cy="20" r="1" fill="rgba(57.0809%,61.8112%,66.1784%,1)"/>
+ <circle cx="4" cy="20" r="1" fill="rgba(67.9057%,76.4706%,83.0671%,1)"/>
+ <circle cx="5" cy="20" r="1" fill="rgba(45.304%,65.9937%,81.2726%,1)"/>
+ <circle cx="6" cy="20" r="1" fill="rgba(27.2465%,54.5296%,74.6944%,1)"/>
+ <circle cx="7" cy="20" r="1" fill="rgba(32.43%,57.7691%,76.4965%,1)"/>
+ <circle cx="8" cy="20" r="1" fill="rgba(32.1859%,57.615%,76.4126%,1)"/>
+ <circle cx="9" cy="20" r="1" fill="rgba(27.4174%,54.6426%,74.7646%,1)"/>
+ <circle cx="10" cy="20" r="1" fill="rgba(25.893%,53.7118%,74.2733%,1)"/>
+ <circle cx="11" cy="20" r="1" fill="rgba(26.7903%,54.2489%,74.5434%,1)"/>
+ <circle cx="12" cy="20" r="1" fill="rgba(27.8187%,54.8867%,74.8928%,1)"/>
+ <circle cx="13" cy="20" r="1" fill="rgba(27.686%,54.8028%,74.847%,1)"/>
+ <circle cx="14" cy="20" r="1" fill="rgba(27.0603%,54.4137%,74.6304%,1)"/>
+ <circle cx="15" cy="20" r="1" fill="rgba(26.8269%,54.2672%,74.5495%,1)"/>
+ <circle cx="16" cy="20" r="1" fill="rgba(27.4266%,54.641%,74.757%,1)"/>
+ <circle cx="17" cy="20" r="1" fill="rgba(26.804%,54.2519%,74.5403%,1)"/>
+ <circle cx="18" cy="20" r="1" fill="rgba(27.129%,54.4549%,74.6532%,1)"/>
+ <circle cx="19" cy="20" r="1" fill="rgba(27.7592%,54.8501%,74.873%,1)"/>
+ <circle cx="20" cy="20" r="1" fill="rgba(27.779%,54.8608%,74.8791%,1)"/>
+ <circle cx="21" cy="20" r="1" fill="rgba(26.5782%,54.1192%,74.4732%,1)"/>
+ <circle cx="22" cy="20" r="1" fill="rgba(25.9709%,53.7606%,74.3008%,1)"/>
+ <circle cx="23" cy="20" r="1" fill="rgba(27.8767%,54.9279%,74.9218%,1)"/>
+ <circle cx="24" cy="20" r="1" fill="rgba(32.8969%,58.0606%,76.6598%,1)"/>
+ <circle cx="25" cy="20" r="1" fill="rgba(31.519%,57.2%,76.1807%,1)"/>
+ <circle cx="26" cy="20" r="1" fill="rgba(27.509%,54.7097%,74.8135%,1)"/>
+ <circle cx="27" cy="20" r="1" fill="rgba(50.8232%,69.0135%,82.4765%,1)"/>
+ <circle cx="28" cy="20" r="1" fill="rgba(64.0543%,69.2531%,73.7316%,1)"/>
+ <circle cx="29" cy="20" r="1" fill="rgba(59.7055%,61.21%,63.3661%,1)"/>
+ <circle cx="30" cy="20" r="1" fill="rgba(63.7522%,62.0584%,61.9806%,1)"/>
+ <circle cx="31" cy="20" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="21" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="21" r="1" fill="rgba(64.271%,62.594%,62.5132%,1)"/>
+ <circle cx="2" cy="21" r="1" fill="rgba(61.5045%,61.8311%,63.1556%,1)"/>
+ <circle cx="3" cy="21" r="1" fill="rgba(34.9767%,56.2493%,72.2118%,1)"/>
+ <circle cx="4" cy="21" r="1" fill="rgba(54.0078%,71.3634%,84.1764%,1)"/>
+ <circle cx="5" cy="21" r="1" fill="rgba(61.9867%,76.2509%,86.7842%,1)"/>
+ <circle cx="6" cy="21" r="1" fill="rgba(26.5736%,54.1085%,74.461%,1)"/>
+ <circle cx="7" cy="21" r="1" fill="rgba(66.6575%,79.1623%,88.4047%,1)"/>
+ <circle cx="8" cy="21" r="1" fill="rgba(74.4793%,84.0497%,91.1238%,1)"/>
+ <circle cx="9" cy="21" r="1" fill="rgba(67.6509%,79.7833%,88.7495%,1)"/>
+ <circle cx="10" cy="21" r="1" fill="rgba(58.3703%,73.9818%,85.5207%,1)"/>
+ <circle cx="11" cy="21" r="1" fill="rgba(32.6253%,57.8912%,76.5652%,1)"/>
+ <circle cx="12" cy="21" r="1" fill="rgba(27.3793%,54.612%,74.7402%,1)"/>
+ <circle cx="13" cy="21" r="1" fill="rgba(30.3532%,56.4706%,75.7748%,1)"/>
+ <circle cx="14" cy="21" r="1" fill="rgba(40.8423%,63.0259%,79.4232%,1)"/>
+ <circle cx="15" cy="21" r="1" fill="rgba(42.385%,63.9902%,79.9603%,1)"/>
+ <circle cx="16" cy="21" r="1" fill="rgba(42.1469%,63.8422%,79.8764%,1)"/>
+ <circle cx="17" cy="21" r="1" fill="rgba(42.4598%,64.0375%,79.9863%,1)"/>
+ <circle cx="18" cy="21" r="1" fill="rgba(39.7086%,62.3178%,79.0295%,1)"/>
+ <circle cx="19" cy="21" r="1" fill="rgba(29.218%,55.761%,75.3796%,1)"/>
+ <circle cx="20" cy="21" r="1" fill="rgba(27.2969%,54.5602%,74.7127%,1)"/>
+ <circle cx="21" cy="21" r="1" fill="rgba(35.761%,59.852%,77.6562%,1)"/>
+ <circle cx="22" cy="21" r="1" fill="rgba(61.0193%,75.6374%,86.4424%,1)"/>
+ <circle cx="23" cy="21" r="1" fill="rgba(68.2017%,80.1282%,88.9403%,1)"/>
+ <circle cx="24" cy="21" r="1" fill="rgba(76.3149%,85.1957%,91.7617%,1)"/>
+ <circle cx="25" cy="21" r="1" fill="rgba(59.7772%,74.8562%,86.0075%,1)"/>
+ <circle cx="26" cy="21" r="1" fill="rgba(26.5766%,54.1085%,74.4594%,1)"/>
+ <circle cx="27" cy="21" r="1" fill="rgba(68.2673%,80.1755%,88.9784%,1)"/>
+ <circle cx="28" cy="21" r="1" fill="rgba(45.6413%,65.6764%,80.5112%,1)"/>
+ <circle cx="29" cy="21" r="1" fill="rgba(47.097%,58.5321%,67.631%,1)"/>
+ <circle cx="30" cy="21" r="1" fill="rgba(64.155%,62.1424%,61.8402%,1)"/>
+ <circle cx="31" cy="21" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="22" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="22" r="1" fill="rgba(64.21%,62.5818%,62.533%,1)"/>
+ <circle cx="2" cy="22" r="1" fill="rgba(62.5422%,62.063%,62.826%,1)"/>
+ <circle cx="3" cy="22" r="1" fill="rgba(35.8831%,56.1242%,71.3771%,1)"/>
+ <circle cx="4" cy="22" r="1" fill="rgba(44.6555%,65.6519%,81.146%,1)"/>
+ <circle cx="5" cy="22" r="1" fill="rgba(75.1675%,84.48%,91.3588%,1)"/>
+ <circle cx="6" cy="22" r="1" fill="rgba(48.484%,67.8019%,82.0813%,1)"/>
+ <circle cx="7" cy="22" r="1" fill="rgba(72.578%,82.8611%,90.4646%,1)"/>
+ <circle cx="8" cy="22" r="1" fill="rgba(44.5136%,65.3193%,80.7004%,1)"/>
+ <circle cx="9" cy="22" r="1" fill="rgba(41.0224%,63.1403%,79.4858%,1)"/>
+ <circle cx="10" cy="22" r="1" fill="rgba(73.7133%,83.5752%,90.8568%,1)"/>
+ <circle cx="11" cy="22" r="1" fill="rgba(41.5625%,63.4745%,79.675%,1)"/>
+ <circle cx="12" cy="22" r="1" fill="rgba(25.2064%,53.254%,73.9849%,1)"/>
+ <circle cx="13" cy="22" r="1" fill="rgba(43.5981%,64.7486%,80.3815%,1)"/>
+ <circle cx="14" cy="22" r="1" fill="rgba(78.5977%,86.6255%,92.5551%,1)"/>
+ <circle cx="15" cy="22" r="1" fill="rgba(66.3554%,78.9731%,88.2963%,1)"/>
+ <circle cx="16" cy="22" r="1" fill="rgba(66.5187%,79.0707%,88.3558%,1)"/>
+ <circle cx="17" cy="22" r="1" fill="rgba(67.1595%,79.4766%,88.5756%,1)"/>
+ <circle cx="18" cy="22" r="1" fill="rgba(78.0682%,86.2959%,92.3705%,1)"/>
+ <circle cx="19" cy="22" r="1" fill="rgba(37.1588%,60.7263%,78.1415%,1)"/>
+ <circle cx="20" cy="22" r="1" fill="rgba(25.1759%,53.2341%,73.9742%,1)"/>
+ <circle cx="21" cy="22" r="1" fill="rgba(49.1432%,68.22%,82.3102%,1)"/>
+ <circle cx="22" cy="22" r="1" fill="rgba(69.9687%,81.2329%,89.5521%,1)"/>
+ <circle cx="23" cy="22" r="1" fill="rgba(38.5885%,61.6175%,78.6389%,1)"/>
+ <circle cx="24" cy="22" r="1" fill="rgba(50.2449%,68.8975%,82.6932%,1)"/>
+ <circle cx="25" cy="22" r="1" fill="rgba(69.4423%,80.8927%,89.3675%,1)"/>
+ <circle cx="26" cy="22" r="1" fill="rgba(50.0496%,68.7816%,82.6246%,1)"/>
+ <circle cx="27" cy="22" r="1" fill="rgba(76.3958%,85.2506%,91.7967%,1)"/>
+ <circle cx="28" cy="22" r="1" fill="rgba(38.5595%,61.6419%,78.7015%,1)"/>
+ <circle cx="29" cy="22" r="1" fill="rgba(49.2988%,59.0555%,66.978%,1)"/>
+ <circle cx="30" cy="22" r="1" fill="rgba(64.21%,62.153%,61.8219%,1)"/>
+ <circle cx="31" cy="22" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="23" r="1" fill="rgba(83.9948%,83.299%,83.299%,1)"/>
+ <circle cx="1" cy="23" r="1" fill="rgba(64.1291%,62.565%,62.562%,1)"/>
+ <circle cx="2" cy="23" r="1" fill="rgba(64.2359%,62.4125%,62.2339%,1)"/>
+ <circle cx="3" cy="23" r="1" fill="rgba(46.6758%,58.7213%,68.2338%,1)"/>
+ <circle cx="4" cy="23" r="1" fill="rgba(30.248%,56.5072%,75.9091%,1)"/>
+ <circle cx="5" cy="23" r="1" fill="rgba(47.8492%,67.4159%,81.8769%,1)"/>
+ <circle cx="6" cy="23" r="1" fill="rgba(65.1484%,78.2177%,87.8782%,1)"/>
+ <circle cx="7" cy="23" r="1" fill="rgba(74.4488%,84.0299%,91.1131%,1)"/>
+ <circle cx="8" cy="23" r="1" fill="rgba(35.2712%,59.5438%,77.4853%,1)"/>
+ <circle cx="9" cy="23" r="1" fill="rgba(26.4393%,54.0261%,74.4137%,1)"/>
+ <circle cx="10" cy="23" r="1" fill="rgba(66.9627%,79.3561%,88.5069%,1)"/>
+ <circle cx="11" cy="23" r="1" fill="rgba(59.0951%,74.432%,85.774%,1)"/>
+ <circle cx="12" cy="23" r="1" fill="rgba(40.4486%,62.7802%,79.2859%,1)"/>
+ <circle cx="13" cy="23" r="1" fill="rgba(53.5042%,70.9407%,83.827%,1)"/>
+ <circle cx="14" cy="23" r="1" fill="rgba(63.6011%,77.2549%,87.3396%,1)"/>
+ <circle cx="15" cy="23" r="1" fill="rgba(27.2862%,54.5541%,74.7082%,1)"/>
+ <circle cx="16" cy="23" r="1" fill="rgba(27.9545%,54.9706%,74.9401%,1)"/>
+ <circle cx="17" cy="23" r="1" fill="rgba(28.9006%,55.5627%,75.2682%,1)"/>
+ <circle cx="18" cy="23" r="1" fill="rgba(69.0059%,80.6332%,89.2164%,1)"/>
+ <circle cx="19" cy="23" r="1" fill="rgba(47.8874%,67.4327%,81.8723%,1)"/>
+ <circle cx="20" cy="23" r="1" fill="rgba(41.5381%,63.4607%,79.6658%,1)"/>
+ <circle cx="21" cy="23" r="1" fill="rgba(64.6494%,77.9095%,87.7043%,1)"/>
+ <circle cx="22" cy="23" r="1" fill="rgba(59.7314%,74.8333%,85.9907%,1)"/>
+ <circle cx="23" cy="23" r="1" fill="rgba(25.2415%,53.2753%,73.9971%,1)"/>
+ <circle cx="24" cy="23" r="1" fill="rgba(40.8011%,62.9984%,79.4079%,1)"/>
+ <circle cx="25" cy="23" r="1" fill="rgba(76.0235%,85.0126%,91.6594%,1)"/>
+ <circle cx="26" cy="23" r="1" fill="rgba(62.6383%,76.6476%,87.0024%,1)"/>
+ <circle cx="27" cy="23" r="1" fill="rgba(44.5518%,65.4826%,80.9415%,1)"/>
+ <circle cx="28" cy="23" r="1" fill="rgba(33.3211%,56.6079%,73.9513%,1)"/>
+ <circle cx="29" cy="23" r="1" fill="rgba(58.1231%,61.1139%,64.3%,1)"/>
+ <circle cx="30" cy="23" r="1" fill="rgba(63.9521%,62.0996%,61.912%,1)"/>
+ <circle cx="31" cy="23" r="1" fill="rgba(77.2137%,76.2234%,76.2234%,1)"/>
+ <circle cx="0" cy="24" r="1" fill="rgba(83.9872%,83.2914%,83.2914%,1)"/>
+ <circle cx="1" cy="24" r="1" fill="rgba(64.1215%,62.562%,62.562%,1)"/>
+ <circle cx="2" cy="24" r="1" fill="rgba(64.1566%,62.3957%,62.2614%,1)"/>
+ <circle cx="3" cy="24" r="1" fill="rgba(60.2472%,61.5991%,63.6393%,1)"/>
+ <circle cx="4" cy="24" r="1" fill="rgba(36.0327%,56.5194%,71.9295%,1)"/>
+ <circle cx="5" cy="24" r="1" fill="rgba(26.215%,54.1253%,74.7341%,1)"/>
+ <circle cx="6" cy="24" r="1" fill="rgba(27.7485%,54.8486%,74.8791%,1)"/>
+ <circle cx="7" cy="24" r="1" fill="rgba(30.9468%,56.8414%,75.9808%,1)"/>
+ <circle cx="8" cy="24" r="1" fill="rgba(28.3513%,55.2193%,75.079%,1)"/>
+ <circle cx="9" cy="24" r="1" fill="rgba(27.5288%,54.7066%,74.7936%,1)"/>
+ <circle cx="10" cy="24" r="1" fill="rgba(44.3702%,65.2323%,80.65%,1)"/>
+ <circle cx="11" cy="24" r="1" fill="rgba(62.4582%,76.5362%,86.9413%,1)"/>
+ <circle cx="12" cy="24" r="1" fill="rgba(66.9718%,79.3576%,88.513%,1)"/>
+ <circle cx="13" cy="24" r="1" fill="rgba(74.2168%,83.8849%,91.0323%,1)"/>
+ <circle cx="14" cy="24" r="1" fill="rgba(56.2234%,72.6421%,84.7745%,1)"/>
+ <circle cx="15" cy="24" r="1" fill="rgba(27.1443%,54.4656%,74.6593%,1)"/>
+ <circle cx="16" cy="24" r="1" fill="rgba(27.8035%,54.8775%,74.8882%,1)"/>
+ <circle cx="17" cy="24" r="1" fill="rgba(28.1498%,55.0942%,75.0088%,1)"/>
+ <circle cx="18" cy="24" r="1" fill="rgba(62.649%,76.6583%,87.0069%,1)"/>
+ <circle cx="19" cy="24" r="1" fill="rgba(72.7901%,82.9953%,90.5348%,1)"/>
+ <circle cx="20" cy="24" r="1" fill="rgba(66.4179%,79.0112%,88.3192%,1)"/>
+ <circle cx="21" cy="24" r="1" fill="rgba(61.2802%,75.8007%,86.5324%,1)"/>
+ <circle cx="22" cy="24" r="1" fill="rgba(40.3021%,62.6886%,79.2355%,1)"/>
+ <circle cx="23" cy="24" r="1" fill="rgba(27.2923%,54.5586%,74.7112%,1)"/>
+ <circle cx="24" cy="24" r="1" fill="rgba(28.7663%,55.4788%,75.2224%,1)"/>
+ <circle cx="25" cy="24" r="1" fill="rgba(30.7973%,56.7468%,75.9258%,1)"/>
+ <circle cx="26" cy="24" r="1" fill="rgba(27.1748%,54.5556%,74.789%,1)"/>
+ <circle cx="27" cy="24" r="1" fill="rgba(27.3259%,54.3984%,74.4213%,1)"/>
+ <circle cx="28" cy="24" r="1" fill="rgba(47.2236%,58.8647%,68.0949%,1)"/>
+ <circle cx="29" cy="24" r="1" fill="rgba(63.946%,62.3606%,62.3499%,1)"/>
+ <circle cx="30" cy="24" r="1" fill="rgba(63.6316%,62.034%,62.0218%,1)"/>
+ <circle cx="31" cy="24" r="1" fill="rgba(77.2045%,76.2142%,76.2142%,1)"/>
+ <circle cx="0" cy="25" r="1" fill="rgba(84.0635%,83.3707%,83.3707%,1)"/>
+ <circle cx="1" cy="25" r="1" fill="rgba(64.1276%,62.5681%,62.5681%,1)"/>
+ <circle cx="2" cy="25" r="1" fill="rgba(63.9094%,62.3453%,62.3484%,1)"/>
+ <circle cx="3" cy="25" r="1" fill="rgba(64.2802%,62.4262%,62.2278%,1)"/>
+ <circle cx="4" cy="25" r="1" fill="rgba(57.2259%,60.9705%,64.6799%,1)"/>
+ <circle cx="5" cy="25" r="1" fill="rgba(35.6832%,56.5209%,72.1752%,1)"/>
+ <circle cx="6" cy="25" r="1" fill="rgba(27.3869%,54.7967%,75.0423%,1)"/>
+ <circle cx="7" cy="25" r="1" fill="rgba(27.4846%,54.7509%,74.8974%,1)"/>
+ <circle cx="8" cy="25" r="1" fill="rgba(27.8141%,54.8821%,74.8898%,1)"/>
+ <circle cx="9" cy="25" r="1" fill="rgba(27.8508%,54.9065%,74.905%,1)"/>
+ <circle cx="10" cy="25" r="1" fill="rgba(27.1275%,54.4549%,74.6532%,1)"/>
+ <circle cx="11" cy="25" r="1" fill="rgba(26.978%,54.3618%,74.6014%,1)"/>
+ <circle cx="12" cy="25" r="1" fill="rgba(28.2536%,55.1583%,75.0439%,1)"/>
+ <circle cx="13" cy="25" r="1" fill="rgba(30.5257%,56.5789%,75.8358%,1)"/>
+ <circle cx="14" cy="25" r="1" fill="rgba(29.4621%,55.9136%,75.465%,1)"/>
+ <circle cx="15" cy="25" r="1" fill="rgba(27.7806%,54.8638%,74.8806%,1)"/>
+ <circle cx="16" cy="25" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="25" r="1" fill="rgba(27.8141%,54.8836%,74.8913%,1)"/>
+ <circle cx="18" cy="25" r="1" fill="rgba(29.9138%,56.1959%,75.6222%,1)"/>
+ <circle cx="19" cy="25" r="1" fill="rgba(30.2266%,56.3912%,75.7305%,1)"/>
+ <circle cx="20" cy="25" r="1" fill="rgba(27.9973%,54.9981%,74.9554%,1)"/>
+ <circle cx="21" cy="25" r="1" fill="rgba(26.8833%,54.3023%,74.5678%,1)"/>
+ <circle cx="22" cy="25" r="1" fill="rgba(27.2801%,54.5495%,74.7066%,1)"/>
+ <circle cx="23" cy="25" r="1" fill="rgba(27.8676%,54.9172%,74.9096%,1)"/>
+ <circle cx="24" cy="25" r="1" fill="rgba(27.7668%,54.8623%,74.8882%,1)"/>
+ <circle cx="25" cy="25" r="1" fill="rgba(27.248%,54.7066%,74.9874%,1)"/>
+ <circle cx="26" cy="25" r="1" fill="rgba(28.8746%,55.111%,74.5357%,1)"/>
+ <circle cx="27" cy="25" r="1" fill="rgba(44.7517%,58.3932%,69.0196%,1)"/>
+ <circle cx="28" cy="25" r="1" fill="rgba(62.6108%,62.0829%,62.8092%,1)"/>
+ <circle cx="29" cy="25" r="1" fill="rgba(64.0589%,62.3819%,62.3056%,1)"/>
+ <circle cx="30" cy="25" r="1" fill="rgba(63.6088%,62.0279%,62.0294%,1)"/>
+ <circle cx="31" cy="25" r="1" fill="rgba(77.2839%,76.2951%,76.2951%,1)"/>
+ <circle cx="0" cy="26" r="1" fill="rgba(86.4393%,85.8503%,85.8503%,1)"/>
+ <circle cx="1" cy="26" r="1" fill="rgba(64.5747%,63.035%,63.035%,1)"/>
+ <circle cx="2" cy="26" r="1" fill="rgba(63.8941%,62.3239%,62.3239%,1)"/>
+ <circle cx="3" cy="26" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="4" cy="26" r="1" fill="rgba(64.2969%,62.4308%,62.2232%,1)"/>
+ <circle cx="5" cy="26" r="1" fill="rgba(59.4583%,61.4313%,63.9048%,1)"/>
+ <circle cx="6" cy="26" r="1" fill="rgba(42.5086%,57.9309%,69.8024%,1)"/>
+ <circle cx="7" cy="26" r="1" fill="rgba(30.0191%,55.3521%,74.1451%,1)"/>
+ <circle cx="8" cy="26" r="1" fill="rgba(27.2862%,54.7875%,75.0958%,1)"/>
+ <circle cx="9" cy="26" r="1" fill="rgba(27.5425%,54.8394%,75.0057%,1)"/>
+ <circle cx="10" cy="26" r="1" fill="rgba(27.805%,54.8943%,74.9157%,1)"/>
+ <circle cx="11" cy="26" r="1" fill="rgba(27.8447%,54.902%,74.902%,1)"/>
+ <circle cx="12" cy="26" r="1" fill="rgba(27.8187%,54.8867%,74.8928%,1)"/>
+ <circle cx="13" cy="26" r="1" fill="rgba(27.7058%,54.8165%,74.8547%,1)"/>
+ <circle cx="14" cy="26" r="1" fill="rgba(27.744%,54.8394%,74.8669%,1)"/>
+ <circle cx="15" cy="26" r="1" fill="rgba(27.8462%,54.905%,74.9035%,1)"/>
+ <circle cx="16" cy="26" r="1" fill="rgba(71,140,191,1)"/>
+ <circle cx="17" cy="26" r="1" fill="rgba(27.8447%,54.9035%,74.902%,1)"/>
+ <circle cx="18" cy="26" r="1" fill="rgba(27.7195%,54.8241%,74.8592%,1)"/>
+ <circle cx="19" cy="26" r="1" fill="rgba(27.7256%,54.8287%,74.8608%,1)"/>
+ <circle cx="20" cy="26" r="1" fill="rgba(27.8264%,54.8913%,74.8959%,1)"/>
+ <circle cx="21" cy="26" r="1" fill="rgba(27.8401%,54.902%,74.9035%,1)"/>
+ <circle cx="22" cy="26" r="1" fill="rgba(27.7287%,54.8791%,74.9416%,1)"/>
+ <circle cx="23" cy="26" r="1" fill="rgba(27.3655%,54.8028%,75.0683%,1)"/>
+ <circle cx="24" cy="26" r="1" fill="rgba(27.7195%,54.876%,74.9447%,1)"/>
+ <circle cx="25" cy="26" r="1" fill="rgba(33.9117%,56.1547%,72.7916%,1)"/>
+ <circle cx="26" cy="26" r="1" fill="rgba(50.4295%,59.5666%,67.0466%,1)"/>
+ <circle cx="27" cy="26" r="1" fill="rgba(63.1159%,62.1866%,62.6337%,1)"/>
+ <circle cx="28" cy="26" r="1" fill="rgba(64.1016%,62.3896%,62.2904%,1)"/>
+ <circle cx="29" cy="26" r="1" fill="rgba(63.917%,62.3529%,62.356%,1)"/>
+ <circle cx="30" cy="26" r="1" fill="rgba(63.7232%,62.1469%,62.1469%,1)"/>
+ <circle cx="31" cy="26" r="1" fill="rgba(79.8306%,78.9532%,78.9532%,1)"/>
+ <circle cx="0" cy="27" r="1" fill="rgba(93.1426%,92.845%,92.845%,1)"/>
+ <circle cx="1" cy="27" r="1" fill="rgba(67.5502%,66.1402%,66.1402%,1)"/>
+ <circle cx="2" cy="27" r="1" fill="rgba(63.682%,62.1027%,62.1027%,1)"/>
+ <circle cx="3" cy="27" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="4" cy="27" r="1" fill="rgba(63.917%,62.3514%,62.3545%,1)"/>
+ <circle cx="5" cy="27" r="1" fill="rgba(64.2283%,62.4155%,62.2461%,1)"/>
+ <circle cx="6" cy="27" r="1" fill="rgba(63.3555%,62.237%,62.5498%,1)"/>
+ <circle cx="7" cy="27" r="1" fill="rgba(55.0591%,60.5234%,65.4368%,1)"/>
+ <circle cx="8" cy="27" r="1" fill="rgba(41.9715%,57.8195%,69.9886%,1)"/>
+ <circle cx="9" cy="27" r="1" fill="rgba(32.4514%,55.8541%,73.2998%,1)"/>
+ <circle cx="10" cy="27" r="1" fill="rgba(28.3421%,55.0057%,74.7295%,1)"/>
+ <circle cx="11" cy="27" r="1" fill="rgba(27.3014%,54.7906%,75.0896%,1)"/>
+ <circle cx="12" cy="27" r="1" fill="rgba(27.2587%,54.7814%,75.1049%,1)"/>
+ <circle cx="13" cy="27" r="1" fill="rgba(27.4083%,54.8119%,75.053%,1)"/>
+ <circle cx="14" cy="27" r="1" fill="rgba(27.5349%,54.8379%,75.0088%,1)"/>
+ <circle cx="15" cy="27" r="1" fill="rgba(27.6066%,54.8531%,74.9844%,1)"/>
+ <circle cx="16" cy="27" r="1" fill="rgba(27.6219%,54.8562%,74.9783%,1)"/>
+ <circle cx="17" cy="27" r="1" fill="rgba(27.5822%,54.8486%,74.992%,1)"/>
+ <circle cx="18" cy="27" r="1" fill="rgba(27.4876%,54.8287%,75.0256%,1)"/>
+ <circle cx="19" cy="27" r="1" fill="rgba(27.3411%,54.7982%,75.0759%,1)"/>
+ <circle cx="20" cy="27" r="1" fill="rgba(27.2297%,54.7753%,75.1156%,1)"/>
+ <circle cx="21" cy="27" r="1" fill="rgba(27.5364%,54.8379%,75.0088%,1)"/>
+ <circle cx="22" cy="27" r="1" fill="rgba(29.5689%,55.259%,74.3023%,1)"/>
+ <circle cx="23" cy="27" r="1" fill="rgba(35.8053%,56.5454%,72.1309%,1)"/>
+ <circle cx="24" cy="27" r="1" fill="rgba(47.5334%,58.9685%,68.0522%,1)"/>
+ <circle cx="25" cy="27" r="1" fill="rgba(59.6811%,61.4771%,63.827%,1)"/>
+ <circle cx="26" cy="27" r="1" fill="rgba(64.2832%,62.4277%,62.2278%,1)"/>
+ <circle cx="27" cy="27" r="1" fill="rgba(64.0162%,62.3728%,62.3209%,1)"/>
+ <circle cx="28" cy="27" r="1" fill="rgba(63.917%,62.3514%,62.3545%,1)"/>
+ <circle cx="29" cy="27" r="1" fill="rgba(63.8437%,62.2721%,62.2721%,1)"/>
+ <circle cx="30" cy="27" r="1" fill="rgba(65.1453%,63.6301%,63.6301%,1)"/>
+ <circle cx="31" cy="27" r="1" fill="rgba(87.8477%,87.3198%,87.3198%,1)"/>
+ <circle cx="0" cy="28" r="1" fill="rgba(99.3515%,99.324%,99.324%,1)"/>
+ <circle cx="1" cy="28" r="1" fill="rgba(78.4466%,77.5082%,77.5082%,1)"/>
+ <circle cx="2" cy="28" r="1" fill="rgba(63.386%,61.7929%,61.7929%,1)"/>
+ <circle cx="3" cy="28" r="1" fill="rgba(63.9063%,62.3377%,62.3377%,1)"/>
+ <circle cx="4" cy="28" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="5" cy="28" r="1" fill="rgba(63.9185%,62.3529%,62.3545%,1)"/>
+ <circle cx="6" cy="28" r="1" fill="rgba(63.9811%,62.3651%,62.3331%,1)"/>
+ <circle cx="7" cy="28" r="1" fill="rgba(64.3931%,62.4506%,62.1881%,1)"/>
+ <circle cx="8" cy="28" r="1" fill="rgba(63.682%,62.3041%,62.4369%,1)"/>
+ <circle cx="9" cy="28" r="1" fill="rgba(59.2889%,61.3977%,63.9658%,1)"/>
+ <circle cx="10" cy="28" r="1" fill="rgba(51.9249%,59.8764%,66.5263%,1)"/>
+ <circle cx="11" cy="28" r="1" fill="rgba(44.4251%,58.3276%,69.1341%,1)"/>
+ <circle cx="12" cy="28" r="1" fill="rgba(38.584%,57.1191%,71.1666%,1)"/>
+ <circle cx="13" cy="28" r="1" fill="rgba(34.7936%,56.3363%,72.4849%,1)"/>
+ <circle cx="14" cy="28" r="1" fill="rgba(32.6085%,55.8862%,73.2448%,1)"/>
+ <circle cx="15" cy="28" r="1" fill="rgba(31.5084%,55.6588%,73.6263%,1)"/>
+ <circle cx="16" cy="28" r="1" fill="rgba(31.2734%,55.6115%,73.7072%,1)"/>
+ <circle cx="17" cy="28" r="1" fill="rgba(31.8685%,55.7336%,73.5027%,1)"/>
+ <circle cx="18" cy="28" r="1" fill="rgba(33.3806%,56.0449%,72.9763%,1)"/>
+ <circle cx="19" cy="28" r="1" fill="rgba(36.1852%,56.6247%,72.0012%,1)"/>
+ <circle cx="20" cy="28" r="1" fill="rgba(40.8255%,57.583%,70.3868%,1)"/>
+ <circle cx="21" cy="28" r="1" fill="rgba(47.5044%,58.9624%,68.0644%,1)"/>
+ <circle cx="22" cy="28" r="1" fill="rgba(55.259%,60.5646%,65.3666%,1)"/>
+ <circle cx="23" cy="28" r="1" fill="rgba(61.6739%,61.8891%,63.1342%,1)"/>
+ <circle cx="24" cy="28" r="1" fill="rgba(64.3229%,62.4353%,62.2126%,1)"/>
+ <circle cx="25" cy="28" r="1" fill="rgba(64.1978%,62.4094%,62.2568%,1)"/>
+ <circle cx="26" cy="28" r="1" fill="rgba(63.9231%,62.3529%,62.3529%,1)"/>
+ <circle cx="27" cy="28" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="28" cy="28" r="1" fill="rgba(63.9261%,62.3575%,62.3575%,1)"/>
+ <circle cx="29" cy="28" r="1" fill="rgba(63.3204%,61.7258%,61.7258%,1)"/>
+ <circle cx="30" cy="28" r="1" fill="rgba(73.4371%,72.282%,72.282%,1)"/>
+ <circle cx="31" cy="28" r="1" fill="rgba(97.3617%,97.2473%,97.2473%,1)"/>
+ <circle cx="0" cy="29" r="1" fill="white"/>
+ <circle cx="1" cy="29" r="1" fill="rgba(95.0423%,94.8272%,94.8272%,1)"/>
+ <circle cx="2" cy="29" r="1" fill="rgba(71.9661%,70.7469%,70.7469%,1)"/>
+ <circle cx="3" cy="29" r="1" fill="rgba(63.3356%,61.7426%,61.7426%,1)"/>
+ <circle cx="4" cy="29" r="1" fill="rgba(63.772%,62.1958%,62.1958%,1)"/>
+ <circle cx="5" cy="29" r="1" fill="rgba(63.92%,62.3514%,62.3514%,1)"/>
+ <circle cx="6" cy="29" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="7" cy="29" r="1" fill="rgba(63.92%,62.3529%,62.3529%,1)"/>
+ <circle cx="8" cy="29" r="1" fill="rgba(63.9521%,62.359%,62.3423%,1)"/>
+ <circle cx="9" cy="29" r="1" fill="rgba(64.2145%,62.414%,62.2507%,1)"/>
+ <circle cx="10" cy="29" r="1" fill="rgba(64.5045%,62.4735%,62.15%,1)"/>
+ <circle cx="11" cy="29" r="1" fill="rgba(64.2451%,62.4201%,62.24%,1)"/>
+ <circle cx="12" cy="29" r="1" fill="rgba(63.1647%,62.1973%,62.6169%,1)"/>
+ <circle cx="13" cy="29" r="1" fill="rgba(61.5335%,61.8601%,63.183%,1)"/>
+ <circle cx="14" cy="29" r="1" fill="rgba(59.9359%,61.529%,63.74%,1)"/>
+ <circle cx="15" cy="29" r="1" fill="rgba(58.8159%,61.2985%,64.1291%,1)"/>
+ <circle cx="16" cy="29" r="1" fill="rgba(58.5397%,61.2421%,64.2237%,1)"/>
+ <circle cx="17" cy="29" r="1" fill="rgba(59.2111%,61.3794%,63.9918%,1)"/>
+ <circle cx="18" cy="29" r="1" fill="rgba(60.5798%,61.6632%,63.5157%,1)"/>
+ <circle cx="19" cy="29" r="1" fill="rgba(62.2614%,62.0096%,62.9313%,1)"/>
+ <circle cx="20" cy="29" r="1" fill="rgba(63.7232%,62.3117%,62.4216%,1)"/>
+ <circle cx="21" cy="29" r="1" fill="rgba(64.4526%,62.4628%,62.1683%,1)"/>
+ <circle cx="22" cy="29" r="1" fill="rgba(64.416%,62.4552%,62.1805%,1)"/>
+ <circle cx="23" cy="29" r="1" fill="rgba(64.0696%,62.3835%,62.3011%,1)"/>
+ <circle cx="24" cy="29" r="1" fill="rgba(63.9231%,62.3529%,62.3529%,1)"/>
+ <circle cx="25" cy="29" r="1" fill="rgba(163,159,159,1)"/>
+ <circle cx="26" cy="29" r="1" fill="rgba(63.9231%,62.3545%,62.3545%,1)"/>
+ <circle cx="27" cy="29" r="1" fill="rgba(63.8315%,62.2599%,62.2599%,1)"/>
+ <circle cx="28" cy="29" r="1" fill="rgba(63.3158%,61.7197%,61.7197%,1)"/>
+ <circle cx="29" cy="29" r="1" fill="rgba(68.6366%,67.274%,67.274%,1)"/>
+ <circle cx="30" cy="29" r="1" fill="rgba(91.5679%,91.2016%,91.2016%,1)"/>
+ <circle cx="31" cy="29" r="1" fill="white"/>
+ <circle cx="0" cy="30" r="1" fill="white"/>
+ <circle cx="1" cy="30" r="1" fill="white"/>
+ <circle cx="2" cy="30" r="1" fill="rgba(94.5739%,94.3374%,94.3374%,1)"/>
+ <circle cx="3" cy="30" r="1" fill="rgba(76.7437%,75.7321%,75.7321%,1)"/>
+ <circle cx="4" cy="30" r="1" fill="rgba(66.1479%,64.6769%,64.6769%,1)"/>
+ <circle cx="5" cy="30" r="1" fill="rgba(63.8911%,62.3209%,62.3209%,1)"/>
+ <circle cx="6" cy="30" r="1" fill="rgba(63.653%,62.0722%,62.0722%,1)"/>
+ <circle cx="7" cy="30" r="1" fill="rgba(63.65%,62.0676%,62.0676%,1)"/>
+ <circle cx="8" cy="30" r="1" fill="rgba(63.65%,62.0691%,62.0691%,1)"/>
+ <circle cx="9" cy="30" r="1" fill="rgba(63.65%,62.0691%,62.0691%,1)"/>
+ <circle cx="10" cy="30" r="1" fill="rgba(63.65%,62.0691%,62.0691%,1)"/>
+ <circle cx="11" cy="30" r="1" fill="rgba(63.653%,62.0691%,62.0676%,1)"/>
+ <circle cx="12" cy="30" r="1" fill="rgba(63.6973%,62.0798%,62.0523%,1)"/>
+ <circle cx="13" cy="30" r="1" fill="rgba(63.7995%,62.0996%,62.0172%,1)"/>
+ <circle cx="14" cy="30" r="1" fill="rgba(63.9048%,62.1225%,61.9806%,1)"/>
+ <circle cx="15" cy="30" r="1" fill="rgba(63.9765%,62.1363%,61.9562%,1)"/>
+ <circle cx="16" cy="30" r="1" fill="rgba(63.9933%,62.1408%,61.9501%,1)"/>
+ <circle cx="17" cy="30" r="1" fill="rgba(63.9521%,62.1317%,61.9638%,1)"/>
+ <circle cx="18" cy="30" r="1" fill="rgba(63.8621%,62.1134%,61.9944%,1)"/>
+ <circle cx="19" cy="30" r="1" fill="rgba(63.7522%,62.0905%,62.034%,1)"/>
+ <circle cx="20" cy="30" r="1" fill="rgba(63.6698%,62.0737%,62.0615%,1)"/>
+ <circle cx="21" cy="30" r="1" fill="rgba(63.65%,62.0691%,62.0691%,1)"/>
+ <circle cx="22" cy="30" r="1" fill="rgba(63.65%,62.0691%,62.0691%,1)"/>
+ <circle cx="23" cy="30" r="1" fill="rgba(63.65%,62.0691%,62.0691%,1)"/>
+ <circle cx="24" cy="30" r="1" fill="rgba(63.65%,62.0691%,62.0691%,1)"/>
+ <circle cx="25" cy="30" r="1" fill="rgba(63.6484%,62.0676%,62.0676%,1)"/>
+ <circle cx="26" cy="30" r="1" fill="rgba(63.7903%,62.2156%,62.2156%,1)"/>
+ <circle cx="27" cy="30" r="1" fill="rgba(65.3529%,63.8453%,63.8453%,1)"/>
+ <circle cx="28" cy="30" r="1" fill="rgba(73.7987%,72.6604%,72.6604%,1)"/>
+ <circle cx="29" cy="30" r="1" fill="rgba(91.7433%,91.3848%,91.3848%,1)"/>
+ <circle cx="30" cy="30" r="1" fill="white"/>
+ <circle cx="31" cy="30" r="1" fill="white"/>
+ <circle cx="0" cy="31" r="1" fill="white"/>
+ <circle cx="1" cy="31" r="1" fill="white"/>
+ <circle cx="2" cy="31" r="1" fill="white"/>
+ <circle cx="3" cy="31" r="1" fill="rgba(98.5611%,98.5%,98.5%,1)"/>
+ <circle cx="4" cy="31" r="1" fill="rgba(90.4448%,90.0298%,90.0298%,1)"/>
+ <circle cx="5" cy="31" r="1" fill="rgba(81.854%,81.0651%,81.0651%,1)"/>
+ <circle cx="6" cy="31" r="1" fill="rgba(78.5306%,77.5967%,77.5967%,1)"/>
+ <circle cx="7" cy="31" r="1" fill="rgba(78.3322%,77.3907%,77.3907%,1)"/>
+ <circle cx="8" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="9" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="10" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="11" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="12" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="13" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="14" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="15" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="16" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="17" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="18" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="19" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="20" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="21" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="22" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="23" cy="31" r="1" fill="rgba(78.3474%,77.406%,77.406%,1)"/>
+ <circle cx="24" cy="31" r="1" fill="rgba(78.3413%,77.3983%,77.3983%,1)"/>
+ <circle cx="25" cy="31" r="1" fill="rgba(78.3948%,77.4548%,77.4548%,1)"/>
+ <circle cx="26" cy="31" r="1" fill="rgba(80.8118%,79.9771%,79.9771%,1)"/>
+ <circle cx="27" cy="31" r="1" fill="rgba(88.5771%,88.0797%,88.0797%,1)"/>
+ <circle cx="28" cy="31" r="1" fill="rgba(97.5509%,97.4456%,97.4456%,1)"/>
+ <circle cx="29" cy="31" r="1" fill="white"/>
+ <circle cx="30" cy="31" r="1" fill="white"/>
+ <circle cx="31" cy="31" r="1" fill="white"/>
+</svg>
diff --git a/tools/steam/icon32.ico b/tools/steam/icon32.ico
new file mode 100644
index 0000000000..17637c6784
--- /dev/null
+++ b/tools/steam/icon32.ico
Binary files differ
diff --git a/tools/steam/icons.zip b/tools/steam/icons.zip
new file mode 100644
index 0000000000..eaeee02298
--- /dev/null
+++ b/tools/steam/icons.zip
Binary files differ
diff --git a/tools/steam/large_capsule.png b/tools/steam/large_capsule.png
new file mode 100644
index 0000000000..14c8ff86d7
--- /dev/null
+++ b/tools/steam/large_capsule.png
Binary files differ
diff --git a/tools/steam/main_capsule.png b/tools/steam/main_capsule.png
new file mode 100644
index 0000000000..5af9406d11
--- /dev/null
+++ b/tools/steam/main_capsule.png
Binary files differ
diff --git a/tools/steam/make_icons.sh b/tools/steam/make_icons.sh
new file mode 100644
index 0000000000..111d7bec2c
--- /dev/null
+++ b/tools/steam/make_icons.sh
@@ -0,0 +1,7 @@
+convert -resize 32x32 ../../godot_icon.svg icon32.ico
+convert -resize 32x32 ../../godot_icon.svg icon32.icns
+for s in 16 24 32 64 96 128 256; do convert -resize ${s}x$s ../../godot_icon.svg icon$s.png; done
+zip icons.zip icon*.png
+rm icon*.png
+
+
diff --git a/tools/steam/small_capsule.png b/tools/steam/small_capsule.png
new file mode 100644
index 0000000000..991896728d
--- /dev/null
+++ b/tools/steam/small_capsule.png
Binary files differ
diff --git a/version.py b/version.py
index 6f666f0df9..86e28ec51d 100644
--- a/version.py
+++ b/version.py
@@ -2,7 +2,7 @@ short_name="godot"
name="Godot Engine"
major=2
minor=0
-status="beta"
+status="stable"