[Scummvm-git-logs] scummvm master -> 31dc015df5bef87cb499ac75deca88399402e35a

dreammaster dreammaster at scummvm.org
Mon Jun 14 05:05:19 UTC 2021


This automated email contains information about 66 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
701396361c AGS: Import of fresh codebase
b104d78888 AGS: Enabling disabled blocks, and making ScummVM needed changes
a4569cb180 AGS: Properly remove sound caching
06c5e089fd AGS: Hook up event handling
5f4b6d74e3 AGS: Re-add proper class initializations
c942554810 AGS: Fixes for calling plugins
4eb0c3bc24 AGS: Graphical fixes
87dba2e276 AGS: Re-added checks for SHOULD_QUIT and abort_engine
e468302585 AGS: Standardize the AGS String npos
e73df29f6c AGS: Engine fixes
4b9b2aa95a AGS: Fix mouse handling
7cb1094a60 AGS: Re-enable savegame code
98a9234253 AGS: Hooked in keyboard handling
ef64d0154c AGS: Remove deprecated mouse code
4c5149960b AGS: Fix size of returned assets as ScummVM streams
28e2ec6cb2 AGS: Savegame fixes
c111ef5f45 AGS: Changing ::remove to File::DeleteFile
6263b9ff11 AGS: Do not store keys with null values in the script Dictionary
37178efc40 AGS: Common: String::_cstr always non-null, simplified GetCStr()
fa48200366 AGS: Removed redundant static String::WriteString()
91c7eeef14 AGS: Provided String method variants with "const String&" argument
d57474ce59 AGS: Provided more function variants accepting const String&
adb44e0336 AGS: Replaced few cases of strcmp with String::Compare and equivs
cd8a0cff0d AGS: Removed unnecessary strlen over String
eb1e337edd AGS: Removed String's "const char*" conversion operator
73347d4559 AGS: Remove _G macros from comments
c7ce28934a AGS: fixed formatting in SpriteCache::InitFile()
46ddd20145 AGS: Fixed few type cast warnings
f982d82cc7 AGS: Added MemoryStream
edb1ac0f6c AGS: fixed formatting type for several size_t and soff_t values
2f54b35c65 AGS: fixed CreateStringArray() not adding managed string refs
8d7e13bea7 AGS: fixed crash when displaying text window overlay with no text
15b90c14f3 AGS: picked out VideoMemoryGraphicsDriver::CreateDDB()
c04665d442 AGS: fixed ChangeRoom for <=2.72 games moving character too early
8dc2d1beae AGS: fixed debug mode reset on restoring a save game
8333270f71 AGS: Assetmanager SetSearchPriority never set priority fix
08cd34ecbc AGS: Misleading set outline in fonts.cpp
c7365214d1 AGS: improved the way view clips are remapped for old audio system
9e4bb91403 AGS: Reintroduced a suspend mode in waitForNextFrame
45313d50df AGS: Moved platform variable macros to core/platform.h
b064647fb4 AGS: Removed unnecessary code
e584f41a4c AGS: fixed BufferedStream was not closing file handle on error
a9837a9039 AGS: removed FixSlashAfterToken, not necessary with ConcatPaths
a95ec92e6c AGS: Added comments for WalkBehindMethodEnum
8278e9fa52 AGS: Moved PlaneScaling to Shared
7a3d9aa32b AGS: Removed deprecated comments
9206ecbe4b AGS: Removed mention of NO_MP3_PLAYER
19808ce0c8 AGS: Fixed comment to room_file.h
1028fc40eb AGS: Split room_file.cpp to have generic read functions separate
902521824d AGS: Picked out ReadRoomData() that runs a callback for each block
fdca14a38d AGS: Replaced TreeMap with std::unordered_map for translations
f913067750 AGS: Reimplemented Translation reading in Common, similar to Game and Room
5aef4bbdf0 AGS: Don't quit if script is trying to remove invalid overlay
1432b0e7fd AGS: fixed how decrypt_text's result is null-terminated
7f6b7559be AGS: Picked out data extension read/write algorithm
2d5d34809e AGS: Use shared data ext algorithm when reading/writing rooms
3c26d9c86c AGS: use shared data ext algorithm when reading/writing MGF
7c71a16683 AGS: Use shared data ext algorithm when reading/writing translation
1ce212d506 AGS: removed unused function
0d600fcd9e AGS: Fix rendering 32-bit game screens
347885c6e8 AGS: Change quitprintf to call ScummVM error method
e390466d1d AGS: Re-convert global strings in multi_file_lib
3a60a8db2f AGS: Convert other global strings to const char *
2a11ab1824 AGS: Re-introduce fix for Fatman intro crash
14a8406719 AGS: Fix GUI sprite renderings
31dc015df5 AGS: Fix gcc warnings


Commit: 701396361c3634d050aa84aa95eedd0d050b254e
    https://github.com/scummvm/scummvm/commit/701396361c3634d050aa84aa95eedd0d050b254e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:44-07:00

Commit Message:
AGS: Import of fresh codebase

Changed paths:
  A engines/ags/engine/ac/audio_channel.cpp
  A engines/ags/engine/ac/audio_channel.h
  A engines/ags/engine/ac/audio_clip.cpp
  A engines/ags/engine/ac/audio_clip.h
  A engines/ags/engine/ac/cd_audio.cpp
  A engines/ags/engine/ac/cd_audio.h
  A engines/ags/engine/ac/character_cache.h
  A engines/ags/engine/ac/character_extras.cpp
  A engines/ags/engine/ac/character_extras.h
  A engines/ags/engine/ac/character_info_engine.cpp
  A engines/ags/engine/ac/date_time.cpp
  A engines/ags/engine/ac/date_time.h
  A engines/ags/engine/ac/dialog_options_rendering.cpp
  A engines/ags/engine/ac/dialog_options_rendering.h
  A engines/ags/engine/ac/drawing_surface.cpp
  A engines/ags/engine/ac/drawing_surface.h
  A engines/ags/engine/ac/dynamic_sprite.cpp
  A engines/ags/engine/ac/dynamic_sprite.h
  A engines/ags/engine/ac/dynobj/all_dynamic_classes.h
  A engines/ags/engine/ac/dynobj/all_script_classes.h
  A engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.cpp
  A engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.h
  A engines/ags/engine/ac/dynobj/cc_audio_channel.cpp
  A engines/ags/engine/ac/dynobj/cc_audio_channel.h
  A engines/ags/engine/ac/dynobj/cc_audio_clip.cpp
  A engines/ags/engine/ac/dynobj/cc_audio_clip.h
  A engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
  A engines/ags/engine/ac/dynobj/cc_dynamic_array.h
  A engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
  A engines/ags/engine/ac/dynobj/cc_dynamic_object.h
  A engines/ags/engine/ac/dynobj/cc_dynamic_object_addr_and_manager.h
  A engines/ags/engine/ac/dynobj/cc_gui_object.cpp
  A engines/ags/engine/ac/dynobj/cc_gui_object.h
  A engines/ags/engine/ac/dynobj/managed_object_pool.cpp
  A engines/ags/engine/ac/dynobj/managed_object_pool.h
  A engines/ags/engine/ac/dynobj/script_audio_channel.h
  A engines/ags/engine/ac/dynobj/script_camera.cpp
  A engines/ags/engine/ac/dynobj/script_camera.h
  A engines/ags/engine/ac/dynobj/script_containers.h
  A engines/ags/engine/ac/dynobj/script_date_time.cpp
  A engines/ags/engine/ac/dynobj/script_date_time.h
  A engines/ags/engine/ac/dynobj/script_dialog.h
  A engines/ags/engine/ac/dynobj/script_dialog_options_rendering.cpp
  A engines/ags/engine/ac/dynobj/script_dialog_options_rendering.h
  A engines/ags/engine/ac/dynobj/script_dict.cpp
  A engines/ags/engine/ac/dynobj/script_dict.h
  A engines/ags/engine/ac/dynobj/script_drawing_surface.cpp
  A engines/ags/engine/ac/dynobj/script_drawing_surface.h
  A engines/ags/engine/ac/dynobj/script_dynamic_sprite.cpp
  A engines/ags/engine/ac/dynobj/script_dynamic_sprite.h
  A engines/ags/engine/ac/dynobj/script_file.cpp
  A engines/ags/engine/ac/dynobj/script_file.h
  A engines/ags/engine/ac/dynobj/script_gui.h
  A engines/ags/engine/ac/dynobj/script_hotspot.h
  A engines/ags/engine/ac/dynobj/script_inv_item.h
  A engines/ags/engine/ac/dynobj/script_mouse.h
  A engines/ags/engine/ac/dynobj/script_object.h
  A engines/ags/engine/ac/dynobj/script_overlay.cpp
  A engines/ags/engine/ac/dynobj/script_overlay.h
  A engines/ags/engine/ac/dynobj/script_region.h
  A engines/ags/engine/ac/dynobj/script_set.cpp
  A engines/ags/engine/ac/dynobj/script_set.h
  A engines/ags/engine/ac/dynobj/script_string.cpp
  A engines/ags/engine/ac/dynobj/script_string.h
  A engines/ags/engine/ac/dynobj/script_system.h
  A engines/ags/engine/ac/dynobj/script_user_object.cpp
  A engines/ags/engine/ac/dynobj/script_user_object.h
  A engines/ags/engine/ac/dynobj/script_view_frame.cpp
  A engines/ags/engine/ac/dynobj/script_view_frame.h
  A engines/ags/engine/ac/dynobj/script_viewport.cpp
  A engines/ags/engine/ac/dynobj/script_viewport.h
  A engines/ags/engine/ac/game_setup.cpp
  A engines/ags/engine/ac/game_setup.h
  A engines/ags/engine/ac/game_state.cpp
  A engines/ags/engine/ac/game_state.h
  A engines/ags/engine/ac/global_date_time.cpp
  A engines/ags/engine/ac/global_date_time.h
  A engines/ags/engine/ac/global_drawing_surface.cpp
  A engines/ags/engine/ac/global_drawing_surface.h
  A engines/ags/engine/ac/global_dynamic_sprite.cpp
  A engines/ags/engine/ac/global_dynamic_sprite.h
  A engines/ags/engine/ac/global_inv_window.cpp
  A engines/ags/engine/ac/global_inv_window.h
  A engines/ags/engine/ac/global_inventory_item.cpp
  A engines/ags/engine/ac/global_inventory_item.h
  A engines/ags/engine/ac/global_view_frame.cpp
  A engines/ags/engine/ac/global_view_frame.h
  A engines/ags/engine/ac/global_walk_behind.cpp
  A engines/ags/engine/ac/global_walk_behind.h
  A engines/ags/engine/ac/global_walkable_area.cpp
  A engines/ags/engine/ac/global_walkable_area.h
  A engines/ags/engine/ac/gui_control.cpp
  A engines/ags/engine/ac/gui_control.h
  A engines/ags/engine/ac/gui_inv.cpp
  A engines/ags/engine/ac/interface_button.cpp
  A engines/ags/engine/ac/interface_element.cpp
  A engines/ags/engine/ac/inv_window.cpp
  A engines/ags/engine/ac/inv_window.h
  A engines/ags/engine/ac/inventory_item.cpp
  A engines/ags/engine/ac/inventory_item.h
  A engines/ags/engine/ac/lip_sync.h
  A engines/ags/engine/ac/move_list.cpp
  A engines/ags/engine/ac/move_list.h
  A engines/ags/engine/ac/object_cache.h
  A engines/ags/engine/ac/rich_game_media.cpp
  A engines/ags/engine/ac/rich_game_media.h
  A engines/ags/engine/ac/room_object.cpp
  A engines/ags/engine/ac/room_object.h
  A engines/ags/engine/ac/room_status.cpp
  A engines/ags/engine/ac/room_status.h
  A engines/ags/engine/ac/screen_overlay.cpp
  A engines/ags/engine/ac/screen_overlay.h
  A engines/ags/engine/ac/script_containers.cpp
  A engines/ags/engine/ac/sprite_cache_engine.cpp
  A engines/ags/engine/ac/sprite_list_entry.h
  A engines/ags/engine/ac/statobj/ags_static_object.cpp
  A engines/ags/engine/ac/statobj/ags_static_object.h
  A engines/ags/engine/ac/statobj/static_array.cpp
  A engines/ags/engine/ac/statobj/static_array.h
  A engines/ags/engine/ac/statobj/static_object.h
  A engines/ags/engine/ac/top_bar_settings.h
  A engines/ags/engine/ac/view_frame.cpp
  A engines/ags/engine/ac/view_frame.h
  A engines/ags/engine/ac/walk_behind.cpp
  A engines/ags/engine/ac/walk_behind.h
  A engines/ags/engine/ac/walkable_area.cpp
  A engines/ags/engine/ac/walkable_area.h
  A engines/ags/engine/debugging/ags_editor_debugger.h
  A engines/ags/engine/debugging/console_output_target.cpp
  A engines/ags/engine/debugging/console_output_target.h
  A engines/ags/engine/debugging/dummy_ags_debugger.h
  A engines/ags/engine/debugging/file_based_ags_debugger.cpp
  A engines/ags/engine/debugging/file_based_ags_debugger.h
  A engines/ags/engine/debugging/log_file.cpp
  A engines/ags/engine/debugging/log_file.h
  A engines/ags/engine/debugging/message_buffer.cpp
  A engines/ags/engine/debugging/message_buffer.h
  A engines/ags/engine/device/mouse_w32.cpp
  A engines/ags/engine/device/mouse_w32.h
  A engines/ags/engine/game/savegame_v321.cpp
  A engines/ags/engine/gfx/ali_3d_scummvm.cpp
  A engines/ags/engine/gfx/ali_3d_scummvm.h
  A engines/ags/engine/gfx/gfx_defines.h
  A engines/ags/engine/gfx/gfx_driver_base.cpp
  A engines/ags/engine/gfx/gfx_driver_base.h
  A engines/ags/engine/gfx/gfx_driver_factory.cpp
  A engines/ags/engine/gfx/gfx_driver_factory.h
  A engines/ags/engine/gfx/gfx_driver_factory_base.h
  A engines/ags/engine/gfx/gfx_mode_list.h
  A engines/ags/engine/gfx/gfxfilter_scummvm_renderer.cpp
  A engines/ags/engine/gfx/gfxfilter_scummvm_renderer.h
  A engines/ags/engine/gfx/graphics_driver.h
  A engines/ags/engine/gui/animating_gui_button.cpp
  A engines/ags/engine/gui/animating_gui_button.h
  A engines/ags/engine/gui/csci_dialog.cpp
  A engines/ags/engine/gui/csci_dialog.h
  A engines/ags/engine/gui/gui_dialog.cpp
  A engines/ags/engine/gui/gui_dialog.h
  A engines/ags/engine/gui/gui_dialog_defines.h
  A engines/ags/engine/gui/gui_dialog_internal_defs.h
  A engines/ags/engine/gui/my_controls.h
  A engines/ags/engine/gui/my_label.cpp
  A engines/ags/engine/gui/my_label.h
  A engines/ags/engine/gui/my_listbox.cpp
  A engines/ags/engine/gui/my_listbox.h
  A engines/ags/engine/gui/my_push_button.cpp
  A engines/ags/engine/gui/my_push_button.h
  A engines/ags/engine/gui/my_textbox.cpp
  A engines/ags/engine/gui/my_textbox.h
  A engines/ags/engine/gui/new_control.cpp
  A engines/ags/engine/gui/new_control.h
  A engines/ags/engine/main/main_defines_ex.h
  A engines/ags/engine/main/main_header.h
  A engines/ags/engine/media/audio/ambient_sound.cpp
  A engines/ags/engine/media/audio/ambient_sound.h
  A engines/ags/engine/media/audio/audio_defines.h
  A engines/ags/engine/media/audio/clip_my_midi.cpp
  A engines/ags/engine/media/audio/clip_my_midi.h
  A engines/ags/engine/media/audio/queued_audio_item.cpp
  A engines/ags/engine/media/audio/queued_audio_item.h
  A engines/ags/engine/media/audio/sound_cache.cpp
  A engines/ags/engine/media/audio/sound_cache.h
  A engines/ags/engine/media/audio/sound_clip.cpp
  A engines/ags/engine/media/audio/sound_clip.h
  A engines/ags/engine/platform/base/ags_platform_driver.cpp
  A engines/ags/engine/platform/base/ags_platform_driver.h
  A engines/ags/engine/platform/base/sys_main.cpp
  A engines/ags/engine/platform/base/sys_main.h
  A engines/ags/engine/script/executing_script.cpp
  A engines/ags/engine/script/executing_script.h
  A engines/ags/engine/script/non_blocking_script_function.h
  A engines/ags/engine/script/runtime_script_value.cpp
  A engines/ags/engine/script/runtime_script_value.h
  A engines/ags/engine/script/system_imports.cpp
  A engines/ags/engine/script/system_imports.h
  A engines/ags/engine/util/thread_pthread.h
  A engines/ags/engine/util/thread_std.h
  A engines/ags/engine/util/thread_windows.h
  A engines/ags/lib/allegro/col_blend.cpp
  A engines/ags/lib/allegro/col_blend.h
  A engines/ags/plugins/ags_plugin.cpp
  A engines/ags/plugins/ags_plugin.h
  A engines/ags/plugins/plugin_object_reader.cpp
  A engines/ags/plugins/plugin_object_reader.h
  A engines/ags/shared/ac/audio_clip_type.cpp
  A engines/ags/shared/ac/audio_clip_type.h
  A engines/ags/shared/ac/character_info.cpp
  A engines/ags/shared/ac/character_info.h
  A engines/ags/shared/ac/dialog_topic.cpp
  A engines/ags/shared/ac/dialog_topic.h
  A engines/ags/shared/ac/dynobj/script_audio_clip.cpp
  A engines/ags/shared/ac/dynobj/script_audio_clip.h
  A engines/ags/shared/ac/game_setup_struct.cpp
  A engines/ags/shared/ac/game_setup_struct.h
  A engines/ags/shared/ac/game_setup_struct_base.cpp
  A engines/ags/shared/ac/game_setup_struct_base.h
  A engines/ags/shared/ac/game_struct_defines.h
  A engines/ags/shared/ac/interface_button.h
  A engines/ags/shared/ac/interface_element.h
  A engines/ags/shared/ac/inventory_item_info.cpp
  A engines/ags/shared/ac/inventory_item_info.h
  A engines/ags/shared/ac/keycode.cpp
  A engines/ags/shared/ac/keycode.h
  A engines/ags/shared/ac/mouse_cursor.cpp
  A engines/ags/shared/ac/mouse_cursor.h
  A engines/ags/shared/ac/old_game_setup_struct.h
  A engines/ags/shared/ac/sprite_cache.cpp
  A engines/ags/shared/ac/sprite_cache.h
  A engines/ags/shared/ac/words_dictionary.cpp
  A engines/ags/shared/ac/words_dictionary.h
  A engines/ags/shared/core/asset_manager.cpp
  A engines/ags/shared/core/asset_manager.h
  A engines/ags/shared/debugging/debug_manager.cpp
  A engines/ags/shared/debugging/debug_manager.h
  A engines/ags/shared/debugging/output_handler.h
  A engines/ags/shared/font/ags_font_renderer.h
  A engines/ags/shared/font/ttf_font_renderer.cpp
  A engines/ags/shared/font/ttf_font_renderer.h
  A engines/ags/shared/font/wfn_font.cpp
  A engines/ags/shared/font/wfn_font.h
  A engines/ags/shared/font/wfn_font_renderer.cpp
  A engines/ags/shared/font/wfn_font_renderer.h
  A engines/ags/shared/game/custom_properties.cpp
  A engines/ags/shared/game/custom_properties.h
  A engines/ags/shared/game/plugin_info.h
  A engines/ags/shared/game/room_struct.cpp
  A engines/ags/shared/game/room_struct.h
  A engines/ags/shared/gfx/allegro_bitmap.cpp
  A engines/ags/shared/gfx/allegro_bitmap.h
  A engines/ags/shared/gui/gui_button.cpp
  A engines/ags/shared/gui/gui_button.h
  A engines/ags/shared/gui/gui_defines.h
  A engines/ags/shared/gui/gui_inv.cpp
  A engines/ags/shared/gui/gui_inv.h
  A engines/ags/shared/gui/gui_label.cpp
  A engines/ags/shared/gui/gui_label.h
  A engines/ags/shared/gui/gui_listbox.cpp
  A engines/ags/shared/gui/gui_listbox.h
  A engines/ags/shared/gui/gui_main.cpp
  A engines/ags/shared/gui/gui_main.h
  A engines/ags/shared/gui/gui_object.cpp
  A engines/ags/shared/gui/gui_object.h
  A engines/ags/shared/gui/gui_slider.cpp
  A engines/ags/shared/gui/gui_slider.h
  A engines/ags/shared/gui/gui_textbox.cpp
  A engines/ags/shared/gui/gui_textbox.h
  A engines/ags/shared/util/aligned_stream.cpp
  A engines/ags/shared/util/aligned_stream.h
  A engines/ags/shared/util/buffered_stream.cpp
  A engines/ags/shared/util/buffered_stream.h
  A engines/ags/shared/util/data_stream.cpp
  A engines/ags/shared/util/data_stream.h
  A engines/ags/shared/util/file_stream.cpp
  A engines/ags/shared/util/file_stream.h
  A engines/ags/shared/util/ini_file.cpp
  A engines/ags/shared/util/ini_file.h
  A engines/ags/shared/util/memory_compat.h
  A engines/ags/shared/util/multi_file_lib.cpp
  A engines/ags/shared/util/multi_file_lib.h
  A engines/ags/shared/util/proxy_stream.cpp
  A engines/ags/shared/util/proxy_stream.h
  A engines/ags/shared/util/text_reader.h
  A engines/ags/shared/util/text_stream_reader.cpp
  A engines/ags/shared/util/text_stream_reader.h
  A engines/ags/shared/util/text_stream_writer.cpp
  A engines/ags/shared/util/text_stream_writer.h
  A engines/ags/shared/util/text_writer.h
  A engines/ags/shared/util/wgt2_allg.cpp
  A engines/ags/shared/util/wgt2_allg.h
  R engines/ags/engine/ac/audiochannel.cpp
  R engines/ags/engine/ac/audiochannel.h
  R engines/ags/engine/ac/audioclip.cpp
  R engines/ags/engine/ac/audioclip.h
  R engines/ags/engine/ac/cdaudio.cpp
  R engines/ags/engine/ac/cdaudio.h
  R engines/ags/engine/ac/charactercache.h
  R engines/ags/engine/ac/characterextras.cpp
  R engines/ags/engine/ac/characterextras.h
  R engines/ags/engine/ac/characterinfo_engine.cpp
  R engines/ags/engine/ac/datetime.cpp
  R engines/ags/engine/ac/datetime.h
  R engines/ags/engine/ac/dialogoptionsrendering.cpp
  R engines/ags/engine/ac/dialogoptionsrendering.h
  R engines/ags/engine/ac/drawingsurface.cpp
  R engines/ags/engine/ac/drawingsurface.h
  R engines/ags/engine/ac/dynamicsprite.cpp
  R engines/ags/engine/ac/dynamicsprite.h
  R engines/ags/engine/ac/dynobj/all_dynamicclasses.h
  R engines/ags/engine/ac/dynobj/all_scriptclasses.h
  R engines/ags/engine/ac/dynobj/cc_agsdynamicobject.cpp
  R engines/ags/engine/ac/dynobj/cc_agsdynamicobject.h
  R engines/ags/engine/ac/dynobj/cc_audiochannel.cpp
  R engines/ags/engine/ac/dynobj/cc_audiochannel.h
  R engines/ags/engine/ac/dynobj/cc_audioclip.cpp
  R engines/ags/engine/ac/dynobj/cc_audioclip.h
  R engines/ags/engine/ac/dynobj/cc_dynamicarray.cpp
  R engines/ags/engine/ac/dynobj/cc_dynamicarray.h
  R engines/ags/engine/ac/dynobj/cc_dynamicobject.cpp
  R engines/ags/engine/ac/dynobj/cc_dynamicobject.h
  R engines/ags/engine/ac/dynobj/cc_dynamicobject_addr_and_manager.h
  R engines/ags/engine/ac/dynobj/cc_guiobject.cpp
  R engines/ags/engine/ac/dynobj/cc_guiobject.h
  R engines/ags/engine/ac/dynobj/managedobjectpool.cpp
  R engines/ags/engine/ac/dynobj/managedobjectpool.h
  R engines/ags/engine/ac/dynobj/scriptaudiochannel.h
  R engines/ags/engine/ac/dynobj/scriptcamera.cpp
  R engines/ags/engine/ac/dynobj/scriptcamera.h
  R engines/ags/engine/ac/dynobj/scriptcontainers.h
  R engines/ags/engine/ac/dynobj/scriptdatetime.cpp
  R engines/ags/engine/ac/dynobj/scriptdatetime.h
  R engines/ags/engine/ac/dynobj/scriptdialog.h
  R engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.cpp
  R engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.h
  R engines/ags/engine/ac/dynobj/scriptdict.cpp
  R engines/ags/engine/ac/dynobj/scriptdict.h
  R engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
  R engines/ags/engine/ac/dynobj/scriptdrawingsurface.h
  R engines/ags/engine/ac/dynobj/scriptdynamicsprite.cpp
  R engines/ags/engine/ac/dynobj/scriptdynamicsprite.h
  R engines/ags/engine/ac/dynobj/scriptfile.cpp
  R engines/ags/engine/ac/dynobj/scriptfile.h
  R engines/ags/engine/ac/dynobj/scriptgui.h
  R engines/ags/engine/ac/dynobj/scripthotspot.h
  R engines/ags/engine/ac/dynobj/scriptinvitem.h
  R engines/ags/engine/ac/dynobj/scriptmouse.h
  R engines/ags/engine/ac/dynobj/scriptobject.h
  R engines/ags/engine/ac/dynobj/scriptoverlay.cpp
  R engines/ags/engine/ac/dynobj/scriptoverlay.h
  R engines/ags/engine/ac/dynobj/scriptregion.h
  R engines/ags/engine/ac/dynobj/scriptset.cpp
  R engines/ags/engine/ac/dynobj/scriptset.h
  R engines/ags/engine/ac/dynobj/scriptstring.cpp
  R engines/ags/engine/ac/dynobj/scriptstring.h
  R engines/ags/engine/ac/dynobj/scriptsystem.h
  R engines/ags/engine/ac/dynobj/scriptuserobject.cpp
  R engines/ags/engine/ac/dynobj/scriptuserobject.h
  R engines/ags/engine/ac/dynobj/scriptviewframe.cpp
  R engines/ags/engine/ac/dynobj/scriptviewframe.h
  R engines/ags/engine/ac/dynobj/scriptviewport.cpp
  R engines/ags/engine/ac/dynobj/scriptviewport.h
  R engines/ags/engine/ac/gamesetup.cpp
  R engines/ags/engine/ac/gamesetup.h
  R engines/ags/engine/ac/gamestate.cpp
  R engines/ags/engine/ac/gamestate.h
  R engines/ags/engine/ac/global_datetime.cpp
  R engines/ags/engine/ac/global_datetime.h
  R engines/ags/engine/ac/global_drawingsurface.cpp
  R engines/ags/engine/ac/global_drawingsurface.h
  R engines/ags/engine/ac/global_dynamicsprite.cpp
  R engines/ags/engine/ac/global_dynamicsprite.h
  R engines/ags/engine/ac/global_inventoryitem.cpp
  R engines/ags/engine/ac/global_inventoryitem.h
  R engines/ags/engine/ac/global_invwindow.cpp
  R engines/ags/engine/ac/global_invwindow.h
  R engines/ags/engine/ac/global_viewframe.cpp
  R engines/ags/engine/ac/global_viewframe.h
  R engines/ags/engine/ac/global_walkablearea.cpp
  R engines/ags/engine/ac/global_walkablearea.h
  R engines/ags/engine/ac/global_walkbehind.cpp
  R engines/ags/engine/ac/global_walkbehind.h
  R engines/ags/engine/ac/guicontrol.cpp
  R engines/ags/engine/ac/guicontrol.h
  R engines/ags/engine/ac/guiinv.cpp
  R engines/ags/engine/ac/interfacebutton.cpp
  R engines/ags/engine/ac/interfaceelement.cpp
  R engines/ags/engine/ac/inventoryitem.cpp
  R engines/ags/engine/ac/inventoryitem.h
  R engines/ags/engine/ac/invwindow.cpp
  R engines/ags/engine/ac/invwindow.h
  R engines/ags/engine/ac/keycode.cpp
  R engines/ags/engine/ac/keycode.h
  R engines/ags/engine/ac/lipsync.h
  R engines/ags/engine/ac/movelist.cpp
  R engines/ags/engine/ac/movelist.h
  R engines/ags/engine/ac/objectcache.h
  R engines/ags/engine/ac/richgamemedia.cpp
  R engines/ags/engine/ac/richgamemedia.h
  R engines/ags/engine/ac/roomobject.cpp
  R engines/ags/engine/ac/roomobject.h
  R engines/ags/engine/ac/roomstatus.cpp
  R engines/ags/engine/ac/roomstatus.h
  R engines/ags/engine/ac/screenoverlay.cpp
  R engines/ags/engine/ac/screenoverlay.h
  R engines/ags/engine/ac/scriptcontainers.cpp
  R engines/ags/engine/ac/spritecache_engine.cpp
  R engines/ags/engine/ac/spritelistentry.h
  R engines/ags/engine/ac/statobj/agsstaticobject.cpp
  R engines/ags/engine/ac/statobj/agsstaticobject.h
  R engines/ags/engine/ac/statobj/staticarray.cpp
  R engines/ags/engine/ac/statobj/staticarray.h
  R engines/ags/engine/ac/statobj/staticobject.h
  R engines/ags/engine/ac/topbarsettings.h
  R engines/ags/engine/ac/viewframe.cpp
  R engines/ags/engine/ac/viewframe.h
  R engines/ags/engine/ac/walkablearea.cpp
  R engines/ags/engine/ac/walkablearea.h
  R engines/ags/engine/ac/walkbehind.cpp
  R engines/ags/engine/ac/walkbehind.h
  R engines/ags/engine/debugging/agseditordebugger.h
  R engines/ags/engine/debugging/consoleoutputtarget.cpp
  R engines/ags/engine/debugging/consoleoutputtarget.h
  R engines/ags/engine/debugging/dummyagsdebugger.h
  R engines/ags/engine/debugging/filebasedagsdebugger.cpp
  R engines/ags/engine/debugging/filebasedagsdebugger.h
  R engines/ags/engine/debugging/logfile.cpp
  R engines/ags/engine/debugging/logfile.h
  R engines/ags/engine/debugging/messagebuffer.cpp
  R engines/ags/engine/debugging/messagebuffer.h
  R engines/ags/engine/device/mousew32.cpp
  R engines/ags/engine/device/mousew32.h
  R engines/ags/engine/gfx/ali3dexception.h
  R engines/ags/engine/gfx/ali3dscummvm.cpp
  R engines/ags/engine/gfx/ali3dscummvm.h
  R engines/ags/engine/gfx/gfxdefines.h
  R engines/ags/engine/gfx/gfxdriverbase.cpp
  R engines/ags/engine/gfx/gfxdriverbase.h
  R engines/ags/engine/gfx/gfxdriverfactory.cpp
  R engines/ags/engine/gfx/gfxdriverfactory.h
  R engines/ags/engine/gfx/gfxdriverfactorybase.h
  R engines/ags/engine/gfx/gfxfilter_aad3d.cpp
  R engines/ags/engine/gfx/gfxfilter_aad3d.h
  R engines/ags/engine/gfx/gfxfilter_allegro.cpp
  R engines/ags/engine/gfx/gfxfilter_allegro.h
  R engines/ags/engine/gfx/gfxfilter_d3d.cpp
  R engines/ags/engine/gfx/gfxfilter_d3d.h
  R engines/ags/engine/gfx/gfxfilter_hqx.cpp
  R engines/ags/engine/gfx/gfxfilter_hqx.h
  R engines/ags/engine/gfx/gfxmodelist.h
  R engines/ags/engine/gfx/graphicsdriver.h
  R engines/ags/engine/gfx/hq2x3x.h
  R engines/ags/engine/gui/animatingguibutton.cpp
  R engines/ags/engine/gui/animatingguibutton.h
  R engines/ags/engine/gui/cscidialog.cpp
  R engines/ags/engine/gui/cscidialog.h
  R engines/ags/engine/gui/guidialog.cpp
  R engines/ags/engine/gui/guidialog.h
  R engines/ags/engine/gui/guidialogdefines.h
  R engines/ags/engine/gui/guidialoginternaldefs.h
  R engines/ags/engine/gui/mycontrols.h
  R engines/ags/engine/gui/mylabel.cpp
  R engines/ags/engine/gui/mylabel.h
  R engines/ags/engine/gui/mylistbox.cpp
  R engines/ags/engine/gui/mylistbox.h
  R engines/ags/engine/gui/mypushbutton.cpp
  R engines/ags/engine/gui/mypushbutton.h
  R engines/ags/engine/gui/mytextbox.cpp
  R engines/ags/engine/gui/mytextbox.h
  R engines/ags/engine/gui/newcontrol.cpp
  R engines/ags/engine/gui/newcontrol.h
  R engines/ags/engine/main/main_allegro.h
  R engines/ags/engine/main/maindefines_ex.h
  R engines/ags/engine/main/mainheader.h
  R engines/ags/engine/media/audio/ambientsound.cpp
  R engines/ags/engine/media/audio/ambientsound.h
  R engines/ags/engine/media/audio/audiodefines.h
  R engines/ags/engine/media/audio/clip_mymidi.cpp
  R engines/ags/engine/media/audio/clip_mymidi.h
  R engines/ags/engine/media/audio/queuedaudioitem.cpp
  R engines/ags/engine/media/audio/queuedaudioitem.h
  R engines/ags/engine/media/audio/soundcache.cpp
  R engines/ags/engine/media/audio/soundcache.h
  R engines/ags/engine/media/audio/soundclip.cpp
  R engines/ags/engine/media/audio/soundclip.h
  R engines/ags/engine/platform/base/agsplatformdriver.cpp
  R engines/ags/engine/platform/base/agsplatformdriver.h
  R engines/ags/engine/resource/DefaultGDF.gdf.xml
  R engines/ags/engine/resource/game-1.ICO
  R engines/ags/engine/resource/resource.h
  R engines/ags/engine/resource/tintshader.fx
  R engines/ags/engine/resource/tintshader.fxo
  R engines/ags/engine/resource/tintshaderLegacy.fx
  R engines/ags/engine/resource/tintshaderLegacy.fxo
  R engines/ags/engine/resource/version.rc
  R engines/ags/engine/script/executingscript.cpp
  R engines/ags/engine/script/executingscript.h
  R engines/ags/engine/script/nonblockingscriptfunction.h
  R engines/ags/engine/script/runtimescriptvalue.cpp
  R engines/ags/engine/script/runtimescriptvalue.h
  R engines/ags/engine/script/systemimports.cpp
  R engines/ags/engine/script/systemimports.h
  R engines/ags/engine/util/mutex_psp.h
  R engines/ags/engine/util/mutex_wii.h
  R engines/ags/plugins/agsplugin.cpp
  R engines/ags/plugins/agsplugin.h
  R engines/ags/plugins/pluginobjectreader.h
  R engines/ags/shared/ac/audiocliptype.cpp
  R engines/ags/shared/ac/audiocliptype.h
  R engines/ags/shared/ac/characterinfo.cpp
  R engines/ags/shared/ac/characterinfo.h
  R engines/ags/shared/ac/dialogtopic.cpp
  R engines/ags/shared/ac/dialogtopic.h
  R engines/ags/shared/ac/dynobj/scriptaudioclip.cpp
  R engines/ags/shared/ac/dynobj/scriptaudioclip.h
  R engines/ags/shared/ac/gamesetupstruct.cpp
  R engines/ags/shared/ac/gamesetupstruct.h
  R engines/ags/shared/ac/gamesetupstructbase.cpp
  R engines/ags/shared/ac/gamesetupstructbase.h
  R engines/ags/shared/ac/gamestructdefines.h
  R engines/ags/shared/ac/interfacebutton.h
  R engines/ags/shared/ac/interfaceelement.h
  R engines/ags/shared/ac/inventoryiteminfo.cpp
  R engines/ags/shared/ac/inventoryiteminfo.h
  R engines/ags/shared/ac/mousecursor.cpp
  R engines/ags/shared/ac/mousecursor.h
  R engines/ags/shared/ac/oldgamesetupstruct.h
  R engines/ags/shared/ac/spritecache.cpp
  R engines/ags/shared/ac/spritecache.h
  R engines/ags/shared/ac/wordsdictionary.cpp
  R engines/ags/shared/ac/wordsdictionary.h
  R engines/ags/shared/core/assetmanager.cpp
  R engines/ags/shared/core/assetmanager.h
  R engines/ags/shared/debugging/debugmanager.cpp
  R engines/ags/shared/debugging/debugmanager.h
  R engines/ags/shared/debugging/outputhandler.h
  R engines/ags/shared/font/agsfontrenderer.h
  R engines/ags/shared/font/ttffontrenderer.cpp
  R engines/ags/shared/font/ttffontrenderer.h
  R engines/ags/shared/font/wfnfont.cpp
  R engines/ags/shared/font/wfnfont.h
  R engines/ags/shared/font/wfnfontrenderer.cpp
  R engines/ags/shared/font/wfnfontrenderer.h
  R engines/ags/shared/game/customproperties.cpp
  R engines/ags/shared/game/customproperties.h
  R engines/ags/shared/game/plugininfo.h
  R engines/ags/shared/game/roomstruct.cpp
  R engines/ags/shared/game/roomstruct.h
  R engines/ags/shared/gfx/allegrobitmap.cpp
  R engines/ags/shared/gfx/allegrobitmap.h
  R engines/ags/shared/gui/guibutton.cpp
  R engines/ags/shared/gui/guibutton.h
  R engines/ags/shared/gui/guidefines.h
  R engines/ags/shared/gui/guiinv.cpp
  R engines/ags/shared/gui/guiinv.h
  R engines/ags/shared/gui/guilabel.cpp
  R engines/ags/shared/gui/guilabel.h
  R engines/ags/shared/gui/guilistbox.cpp
  R engines/ags/shared/gui/guilistbox.h
  R engines/ags/shared/gui/guimain.cpp
  R engines/ags/shared/gui/guimain.h
  R engines/ags/shared/gui/guiobject.cpp
  R engines/ags/shared/gui/guiobject.h
  R engines/ags/shared/gui/guislider.cpp
  R engines/ags/shared/gui/guislider.h
  R engines/ags/shared/gui/guitextbox.cpp
  R engines/ags/shared/gui/guitextbox.h
  R engines/ags/shared/util/alignedstream.cpp
  R engines/ags/shared/util/alignedstream.h
  R engines/ags/shared/util/bufferedstream.cpp
  R engines/ags/shared/util/bufferedstream.h
  R engines/ags/shared/util/datastream.cpp
  R engines/ags/shared/util/datastream.h
  R engines/ags/shared/util/filestream.cpp
  R engines/ags/shared/util/filestream.h
  R engines/ags/shared/util/inifile.cpp
  R engines/ags/shared/util/inifile.h
  R engines/ags/shared/util/multifilelib.h
  R engines/ags/shared/util/mutifilelib.cpp
  R engines/ags/shared/util/proxystream.cpp
  R engines/ags/shared/util/proxystream.h
  R engines/ags/shared/util/textreader.h
  R engines/ags/shared/util/textstreamreader.cpp
  R engines/ags/shared/util/textstreamreader.h
  R engines/ags/shared/util/textstreamwriter.cpp
  R engines/ags/shared/util/textstreamwriter.h
  R engines/ags/shared/util/textwriter.h
  R engines/ags/shared/util/wgt2allg.cpp
  R engines/ags/shared/util/wgt2allg.h
    engines/ags/ags.cpp
    engines/ags/ags.h
    engines/ags/console.cpp
    engines/ags/console.h
    engines/ags/detection.cpp
    engines/ags/engine/ac/asset_helper.h
    engines/ags/engine/ac/button.cpp
    engines/ags/engine/ac/button.h
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/character.h
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/dialog.h
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/display.h
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/draw.h
    engines/ags/engine/ac/draw_software.cpp
    engines/ags/engine/ac/draw_software.h
    engines/ags/engine/ac/dynobj/cc_character.cpp
    engines/ags/engine/ac/dynobj/cc_character.h
    engines/ags/engine/ac/dynobj/cc_dialog.cpp
    engines/ags/engine/ac/dynobj/cc_dialog.h
    engines/ags/engine/ac/dynobj/cc_gui.cpp
    engines/ags/engine/ac/dynobj/cc_gui.h
    engines/ags/engine/ac/dynobj/cc_hotspot.cpp
    engines/ags/engine/ac/dynobj/cc_hotspot.h
    engines/ags/engine/ac/dynobj/cc_inventory.cpp
    engines/ags/engine/ac/dynobj/cc_inventory.h
    engines/ags/engine/ac/dynobj/cc_object.cpp
    engines/ags/engine/ac/dynobj/cc_object.h
    engines/ags/engine/ac/dynobj/cc_region.cpp
    engines/ags/engine/ac/dynobj/cc_region.h
    engines/ags/engine/ac/dynobj/cc_serializer.cpp
    engines/ags/engine/ac/dynobj/cc_serializer.h
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/event.h
    engines/ags/engine/ac/file.cpp
    engines/ags/engine/ac/file.h
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/game.h
    engines/ags/engine/ac/global_api.cpp
    engines/ags/engine/ac/global_audio.cpp
    engines/ags/engine/ac/global_audio.h
    engines/ags/engine/ac/global_button.cpp
    engines/ags/engine/ac/global_button.h
    engines/ags/engine/ac/global_character.cpp
    engines/ags/engine/ac/global_character.h
    engines/ags/engine/ac/global_debug.cpp
    engines/ags/engine/ac/global_debug.h
    engines/ags/engine/ac/global_dialog.cpp
    engines/ags/engine/ac/global_dialog.h
    engines/ags/engine/ac/global_display.cpp
    engines/ags/engine/ac/global_file.cpp
    engines/ags/engine/ac/global_file.h
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/ac/global_game.h
    engines/ags/engine/ac/global_gui.cpp
    engines/ags/engine/ac/global_hotspot.cpp
    engines/ags/engine/ac/global_hotspot.h
    engines/ags/engine/ac/global_label.cpp
    engines/ags/engine/ac/global_mouse.cpp
    engines/ags/engine/ac/global_object.cpp
    engines/ags/engine/ac/global_object.h
    engines/ags/engine/ac/global_overlay.cpp
    engines/ags/engine/ac/global_overlay.h
    engines/ags/engine/ac/global_palette.cpp
    engines/ags/engine/ac/global_parser.cpp
    engines/ags/engine/ac/global_parser.h
    engines/ags/engine/ac/global_region.cpp
    engines/ags/engine/ac/global_region.h
    engines/ags/engine/ac/global_room.cpp
    engines/ags/engine/ac/global_screen.cpp
    engines/ags/engine/ac/global_screen.h
    engines/ags/engine/ac/global_slider.cpp
    engines/ags/engine/ac/global_textbox.cpp
    engines/ags/engine/ac/global_timer.cpp
    engines/ags/engine/ac/global_translation.cpp
    engines/ags/engine/ac/global_video.cpp
    engines/ags/engine/ac/global_video.h
    engines/ags/engine/ac/global_viewport.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/ac/gui.h
    engines/ags/engine/ac/hotspot.cpp
    engines/ags/engine/ac/hotspot.h
    engines/ags/engine/ac/label.cpp
    engines/ags/engine/ac/label.h
    engines/ags/engine/ac/listbox.cpp
    engines/ags/engine/ac/listbox.h
    engines/ags/engine/ac/math.cpp
    engines/ags/engine/ac/mouse.cpp
    engines/ags/engine/ac/mouse.h
    engines/ags/engine/ac/object.cpp
    engines/ags/engine/ac/object.h
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/overlay.h
    engines/ags/engine/ac/parser.cpp
    engines/ags/engine/ac/path_helper.h
    engines/ags/engine/ac/properties.cpp
    engines/ags/engine/ac/properties.h
    engines/ags/engine/ac/region.cpp
    engines/ags/engine/ac/region.h
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/ac/room.h
    engines/ags/engine/ac/route_finder.cpp
    engines/ags/engine/ac/route_finder_impl.cpp
    engines/ags/engine/ac/route_finder_impl_legacy.cpp
    engines/ags/engine/ac/route_finder_jps.cpp
    engines/ags/engine/ac/route_finder_jps.h
    engines/ags/engine/ac/runtime_defines.h
    engines/ags/engine/ac/screen.cpp
    engines/ags/engine/ac/screen.h
    engines/ags/engine/ac/slider.cpp
    engines/ags/engine/ac/slider.h
    engines/ags/engine/ac/speech.cpp
    engines/ags/engine/ac/sprite.cpp
    engines/ags/engine/ac/string.cpp
    engines/ags/engine/ac/string.h
    engines/ags/engine/ac/sys_events.cpp
    engines/ags/engine/ac/sys_events.h
    engines/ags/engine/ac/system.cpp
    engines/ags/engine/ac/system.h
    engines/ags/engine/ac/textbox.cpp
    engines/ags/engine/ac/textbox.h
    engines/ags/engine/ac/timer.cpp
    engines/ags/engine/ac/timer.h
    engines/ags/engine/ac/translation.cpp
    engines/ags/engine/ac/translation.h
    engines/ags/engine/ac/tree_map.cpp
    engines/ags/engine/ac/tree_map.h
    engines/ags/engine/ac/viewport_script.cpp
    engines/ags/engine/debugging/debug.cpp
    engines/ags/engine/debugging/debug_log.h
    engines/ags/engine/debugging/debugger.h
    engines/ags/engine/font/fonts_engine.cpp
    engines/ags/engine/game/game_init.cpp
    engines/ags/engine/game/game_init.h
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/game/savegame.h
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/game/savegame_components.h
    engines/ags/engine/game/savegame_internal.h
    engines/ags/engine/game/viewport.cpp
    engines/ags/engine/game/viewport.h
    engines/ags/engine/gfx/blender.cpp
    engines/ags/engine/gfx/blender.h
    engines/ags/engine/gfx/color_engine.cpp
    engines/ags/engine/gfx/gfx_util.cpp
    engines/ags/engine/gfx/gfx_util.h
    engines/ags/engine/gfx/gfxfilter_scaling.h
    engines/ags/engine/gui/gui_engine.cpp
    engines/ags/engine/main/config.cpp
    engines/ags/engine/main/config.h
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/engine.h
    engines/ags/engine/main/engine_setup.cpp
    engines/ags/engine/main/engine_setup.h
    engines/ags/engine/main/game_file.cpp
    engines/ags/engine/main/game_file.h
    engines/ags/engine/main/game_run.cpp
    engines/ags/engine/main/game_run.h
    engines/ags/engine/main/game_start.cpp
    engines/ags/engine/main/graphics_mode.cpp
    engines/ags/engine/main/graphics_mode.h
    engines/ags/engine/main/main.cpp
    engines/ags/engine/main/main.h
    engines/ags/engine/main/quit.cpp
    engines/ags/engine/main/update.cpp
    engines/ags/engine/main/update.h
    engines/ags/engine/media/audio/audio.cpp
    engines/ags/engine/media/audio/audio.h
    engines/ags/engine/media/audio/audio_system.h
    engines/ags/engine/media/audio/sound.cpp
    engines/ags/engine/media/audio/sound.h
    engines/ags/engine/media/video/video.cpp
    engines/ags/engine/platform/scummvm/scummvm_platform_driver.cpp
    engines/ags/engine/script/cc_instance.cpp
    engines/ags/engine/script/cc_instance.h
    engines/ags/engine/script/exports.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/engine/script/script.h
    engines/ags/engine/script/script_api.cpp
    engines/ags/engine/script/script_api.h
    engines/ags/engine/script/script_engine.cpp
    engines/ags/engine/script/script_runtime.cpp
    engines/ags/engine/script/script_runtime.h
    engines/ags/engine/util/library.h
    engines/ags/engine/util/library_scummvm.h
    engines/ags/engine/util/mutex.h
    engines/ags/engine/util/mutex_base.h
    engines/ags/engine/util/mutex_lock.h
    engines/ags/engine/util/mutex_pthread.h
    engines/ags/engine/util/mutex_std.h
    engines/ags/engine/util/mutex_windows.h
    engines/ags/events.cpp
    engines/ags/game_scanner.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/lib/aastr-0.1.1/aarot.cpp
    engines/ags/lib/aastr-0.1.1/aastr.cpp
    engines/ags/lib/aastr-0.1.1/aastr.h
    engines/ags/lib/aastr-0.1.1/aautil.cpp
    engines/ags/lib/aastr-0.1.1/aautil.h
    engines/ags/lib/alfont/alfont.cpp
    engines/ags/lib/alfont/alfont.h
    engines/ags/lib/allegro.h
    engines/ags/lib/allegro/base.h
    engines/ags/lib/allegro/color.cpp
    engines/ags/lib/allegro/color.h
    engines/ags/lib/allegro/draw.cpp
    engines/ags/lib/allegro/error.h
    engines/ags/lib/allegro/file.h
    engines/ags/lib/allegro/flood.cpp
    engines/ags/lib/allegro/fmaths.cpp
    engines/ags/lib/allegro/gfx.cpp
    engines/ags/lib/allegro/gfx.h
    engines/ags/lib/allegro/graphics.cpp
    engines/ags/lib/allegro/keyboard.h
    engines/ags/lib/allegro/math.cpp
    engines/ags/lib/allegro/mouse.cpp
    engines/ags/lib/allegro/surface.cpp
    engines/ags/lib/allegro/surface.h
    engines/ags/lib/allegro/system.h
    engines/ags/lib/std/algorithm.h
    engines/ags/lib/std/array.h
    engines/ags/lib/std/chrono.h
    engines/ags/lib/std/functional.h
    engines/ags/lib/std/limits.h
    engines/ags/lib/std/list.h
    engines/ags/lib/std/map.h
    engines/ags/lib/std/math.h
    engines/ags/lib/std/memory.h
    engines/ags/lib/std/queue.h
    engines/ags/lib/std/set.h
    engines/ags/lib/std/thread.h
    engines/ags/lib/std/type_traits.h
    engines/ags/lib/std/unordered_set.h
    engines/ags/lib/std/utility.h
    engines/ags/lib/std/vector.h
    engines/ags/lib/std/xtr1common.h
    engines/ags/lib/std/xutility.h
    engines/ags/lib/system/datetime.h
    engines/ags/metaengine.cpp
    engines/ags/module.mk
    engines/ags/plugins/ags_blend/ags_blend.h
    engines/ags/plugins/ags_controller/ags_controller.cpp
    engines/ags/plugins/ags_controller/ags_controller.h
    engines/ags/plugins/ags_creditz/ags_creditz.cpp
    engines/ags/plugins/ags_creditz/ags_creditz.h
    engines/ags/plugins/ags_creditz/ags_creditz1.cpp
    engines/ags/plugins/ags_creditz/ags_creditz1.h
    engines/ags/plugins/ags_creditz/ags_creditz2.cpp
    engines/ags/plugins/ags_creditz/ags_creditz2.h
    engines/ags/plugins/ags_creditz/drawing.h
    engines/ags/plugins/ags_flashlight/ags_flashlight.h
    engines/ags/plugins/ags_joy/ags_joy.h
    engines/ags/plugins/ags_nickenstien_gfx/ags_nickenstien_gfx.h
    engines/ags/plugins/ags_pal_render/pal_render.h
    engines/ags/plugins/ags_parallax/ags_parallax.h
    engines/ags/plugins/ags_shell/ags_shell.h
    engines/ags/plugins/ags_snow_rain/ags_snow_rain.h
    engines/ags/plugins/ags_snow_rain/weather.cpp
    engines/ags/plugins/ags_snow_rain/weather.h
    engines/ags/plugins/ags_sprite_font/ags_sprite_font.h
    engines/ags/plugins/ags_sprite_font/ags_sprite_font_clifftop.h
    engines/ags/plugins/ags_sprite_font/character_entry.h
    engines/ags/plugins/ags_sprite_font/sprite_font.h
    engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
    engines/ags/plugins/ags_sprite_font/sprite_font_renderer.h
    engines/ags/plugins/ags_sprite_font/sprite_font_renderer_clifftop.cpp
    engines/ags/plugins/ags_sprite_font/sprite_font_renderer_clifftop.h
    engines/ags/plugins/ags_sprite_font/variable_width_font.cpp
    engines/ags/plugins/ags_sprite_font/variable_width_font.h
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.h
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
    engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.h
    engines/ags/plugins/ags_tcp_ip/ags_tcp_ip.h
    engines/ags/plugins/ags_wadjet_util/ags_wadjet_util.h
    engines/ags/plugins/plugin_base.cpp
    engines/ags/plugins/plugin_base.h
    engines/ags/plugins/plugin_engine.h
    engines/ags/plugins/serializer.h
    engines/ags/shared/ac/common.cpp
    engines/ags/shared/ac/common.h
    engines/ags/shared/ac/common_defines.h
    engines/ags/shared/ac/game_version.h
    engines/ags/shared/ac/view.cpp
    engines/ags/shared/ac/view.h
    engines/ags/shared/api/stream_api.h
    engines/ags/shared/core/asset.cpp
    engines/ags/shared/core/asset.h
    engines/ags/shared/core/def_version.h
    engines/ags/shared/core/platform.h
    engines/ags/shared/core/types.h
    engines/ags/shared/debugging/out.h
    engines/ags/shared/font/fonts.cpp
    engines/ags/shared/font/fonts.h
    engines/ags/shared/game/interactions.cpp
    engines/ags/shared/game/interactions.h
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/game/main_game_file.h
    engines/ags/shared/game/room_file.cpp
    engines/ags/shared/game/room_file.h
    engines/ags/shared/game/room_file_deprecated.cpp
    engines/ags/shared/game/room_version.h
    engines/ags/shared/gfx/bitmap.cpp
    engines/ags/shared/gfx/bitmap.h
    engines/ags/shared/gfx/gfx_def.h
    engines/ags/shared/gfx/image.cpp
    engines/ags/shared/script/cc_error.cpp
    engines/ags/shared/script/cc_error.h
    engines/ags/shared/script/cc_options.h
    engines/ags/shared/script/cc_script.cpp
    engines/ags/shared/script/cc_script.h
    engines/ags/shared/script/script_common.h
    engines/ags/shared/util/bbop.h
    engines/ags/shared/util/compress.cpp
    engines/ags/shared/util/compress.h
    engines/ags/shared/util/directory.cpp
    engines/ags/shared/util/directory.h
    engines/ags/shared/util/file.cpp
    engines/ags/shared/util/geometry.cpp
    engines/ags/shared/util/geometry.h
    engines/ags/shared/util/ini_util.cpp
    engines/ags/shared/util/ini_util.h
    engines/ags/shared/util/lzw.cpp
    engines/ags/shared/util/math.h
    engines/ags/shared/util/memory.h
    engines/ags/shared/util/misc.cpp
    engines/ags/shared/util/misc.h
    engines/ags/shared/util/path.cpp
    engines/ags/shared/util/path.h
    engines/ags/shared/util/stdio_compat.cpp
    engines/ags/shared/util/stream.h
    engines/ags/shared/util/string.cpp
    engines/ags/shared/util/string.h
    engines/ags/shared/util/string_compat.h
    engines/ags/shared/util/string_types.h
    engines/ags/shared/util/string_utils.cpp
    engines/ags/shared/util/string_utils.h
    engines/ags/shared/util/version.cpp
    engines/ags/shared/util/version.h
    engines/ags/tests/test_file.cpp
    engines/ags/tests/test_inifile.cpp
    engines/ags/tests/test_sprintf.cpp
    engines/ags/tests/test_string.cpp


diff --git a/engines/ags/ags.cpp b/engines/ags/ags.cpp
index aac1b0b6d1..08ad6723e6 100644
--- a/engines/ags/ags.cpp
+++ b/engines/ags/ags.cpp
@@ -41,8 +41,8 @@
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/game.h"
 #include "ags/globals.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/room.h"
 #include "ags/shared/core/def_version.h"
 #include "ags/engine/debugging/debugger.h"
@@ -51,13 +51,13 @@
 #include "ags/engine/game/savegame.h"
 #include "ags/engine/main/config.h"
 #include "ags/engine/main/engine.h"
-#include "ags/engine/main/mainheader.h"
+#include "ags/engine/main/main_header.h"
 #include "ags/engine/main/main.h"
 #include "ags/engine/main/quit.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/engine/script/script.h"
 #include "ags/engine/ac/route_finder.h"
-#include "ags/shared/core/assetmanager.h"
+#include "ags/shared/core/asset_manager.h"
 #include "ags/shared/util/directory.h"
 #include "ags/shared/script/cc_options.h"
 
@@ -70,9 +70,9 @@ namespace AGS {
 AGSEngine *g_vm;
 
 AGSEngine::AGSEngine(OSystem *syst, const AGSGameDescription *gameDesc) : Engine(syst),
-		_gameDescription(gameDesc), _randomSource("AGS"), _events(nullptr), _music(nullptr),
-		_rawScreen(nullptr), _screen(nullptr), _gfxDriver(nullptr),
-		_globals(nullptr), _forceTextAA(false) {
+	_gameDescription(gameDesc), _randomSource("AGS"), _events(nullptr), _music(nullptr),
+	_rawScreen(nullptr), _screen(nullptr), _gfxDriver(nullptr),
+	_globals(nullptr), _forceTextAA(false) {
 	g_vm = this;
 
 	_events = new EventsManager();
@@ -87,10 +87,10 @@ AGSEngine::AGSEngine(OSystem *syst, const AGSGameDescription *gameDesc) : Engine
 AGSEngine::~AGSEngine() {
 	if (_G(proper_exit) == 0) {
 		_G(platform)->DisplayAlert("Error: the program has exited without requesting it.\n"
-			"Program pointer: %+03d  (write this number down), ACI version %s\n"
-			"If you see a list of numbers above, please write them down and contact\n"
-			"developers. Otherwise, note down any other information displayed.",
-			_G(our_eip), _G(EngineVersion).LongString.GetCStr());
+		                           "Program pointer: %+03d  (write this number down), ACI version %s\n"
+		                           "If you see a list of numbers above, please write them down and contact\n"
+		                           "developers. Otherwise, note down any other information displayed.",
+		                           _G(our_eip), _G(EngineVersion).LongString.GetCStr());
 	}
 
 	delete _screen;
@@ -135,9 +135,6 @@ Common::Error AGSEngine::run() {
 	const int ARGC = 2;
 	AGS3::main_init(ARGC, ARGV);
 
-#if AGS_PLATFORM_OS_WINDOWS
-	setup_malloc_handling();
-#endif
 	_G(debug_flags) = 0;
 
 	if (ConfMan.hasKey("display_fps"))
@@ -171,23 +168,13 @@ Common::Error AGSEngine::run() {
 
 	_G(loadSaveGameOnStartup) = ConfMan.getInt("save_slot");
 
-#ifdef USE_CUSTOM_EXCEPTION_HANDLER
-	if (_GP(usetup).disable_exception_handling)
-#endif
-	{
-		syncSoundSettings();
-		AGS3::initialize_engine(startup_opts);
+	syncSoundSettings();
+	AGS3::initialize_engine(startup_opts);
 
-		// Do shutdown stuff
-		::AGS3::quit_free();
+	// Do shutdown stuff
+	::AGS3::quit_free();
 
-		return Common::kNoError;
-	}
-#ifdef USE_CUSTOM_EXCEPTION_HANDLER
-	else {
-		return initialize_engine_with_exception_handling(initialize_engine, startup_opts);
-	}
-#endif
+	return Common::kNoError;
 }
 
 SaveStateList AGSEngine::listSaves() const {
@@ -209,12 +196,12 @@ void AGSEngine::setGraphicsMode(size_t w, size_t h) {
 
 bool AGSEngine::canLoadGameStateCurrently() {
 	return !_GP(thisroom).Options.SaveLoadDisabled &&
-		!_G(inside_script) && !_GP(play).fast_forward && !_G(no_blocking_functions);
+	       !_G(inside_script) && !_GP(play).fast_forward && !_G(no_blocking_functions);
 }
 
 bool AGSEngine::canSaveGameStateCurrently() {
 	return !_GP(thisroom).Options.SaveLoadDisabled &&
-		!_G(inside_script) && !_GP(play).fast_forward && !_G(no_blocking_functions);
+	       !_G(inside_script) && !_GP(play).fast_forward && !_G(no_blocking_functions);
 }
 
 Common::Error AGSEngine::loadGameState(int slot) {
diff --git a/engines/ags/ags.h b/engines/ags/ags.h
index 751dfebe3e..4b5b972806 100644
--- a/engines/ags/ags.h
+++ b/engines/ags/ags.h
@@ -119,9 +119,9 @@ public:
 
 	bool hasFeature(EngineFeature f) const override {
 		return
-			(f == kSupportsLoadingDuringRuntime) ||
-			(f == kSupportsSavingDuringRuntime) ||
-			(f == kSupportsReturnToLauncher);
+		    (f == kSupportsLoadingDuringRuntime) ||
+		    (f == kSupportsSavingDuringRuntime) ||
+		    (f == kSupportsReturnToLauncher);
 	};
 
 	/**
diff --git a/engines/ags/console.cpp b/engines/ags/console.cpp
index 345e3b8a61..3366a8722c 100644
--- a/engines/ags/console.cpp
+++ b/engines/ags/console.cpp
@@ -23,8 +23,8 @@
 #include "ags/console.h"
 #include "ags/ags.h"
 #include "ags/globals.h"
-#include "ags/shared/ac/spritecache.h"
-#include "ags/shared/gfx/allegrobitmap.h"
+#include "ags/shared/ac/sprite_cache.h"
+#include "ags/shared/gfx/allegro_bitmap.h"
 #include "ags/shared/script/cc_options.h"
 #include "image/png.h"
 
@@ -61,8 +61,8 @@ static const LevelName levelNames[] = {
 	{nullptr, AGS3::AGS::Shared::kDbgMsg_None}
 };
 
-struct GroupName{
-	const char* name;
+struct GroupName {
+	const char *name;
 	AGS3::uint32_t group;
 };
 
diff --git a/engines/ags/console.h b/engines/ags/console.h
index 45af92fb39..dddd0fb2c8 100644
--- a/engines/ags/console.h
+++ b/engines/ags/console.h
@@ -25,8 +25,8 @@
 #define AGS_CONSOLE_H
 
 #include "gui/debugger.h"
-#include "ags/shared/debugging/debugmanager.h"
-#include "ags/shared/debugging/outputhandler.h"
+#include "ags/shared/debugging/debug_manager.h"
+#include "ags/shared/debugging/output_handler.h"
 #include "ags/shared/core/types.h"
 
 namespace AGS {
diff --git a/engines/ags/detection.cpp b/engines/ags/detection.cpp
index 9896dd9e86..51aa26e9cf 100644
--- a/engines/ags/detection.cpp
+++ b/engines/ags/detection.cpp
@@ -53,13 +53,13 @@ static bool isAGSFile(Common::File &f) {
 	// Check for signature at beginning of file
 	char buffer[16];
 	if (f.read(buffer, HEAD_SIG_SIZE) == HEAD_SIG_SIZE &&
-			!memcmp(buffer, HEAD_SIG, HEAD_SIG_SIZE))
+	        !memcmp(buffer, HEAD_SIG, HEAD_SIG_SIZE))
 		return true;
 
 	// Check for signature at end of EXE files
 	f.seek(-TAIL_SIG_SIZE, SEEK_END);
 	if (f.read(buffer, TAIL_SIG_SIZE) == TAIL_SIG_SIZE &&
-		!memcmp(buffer, TAIL_SIG, TAIL_SIG_SIZE))
+	        !memcmp(buffer, TAIL_SIG, TAIL_SIG_SIZE))
 		return true;
 
 	return false;
@@ -84,14 +84,14 @@ private:
 };
 
 AGSOptionsWidget::AGSOptionsWidget(GuiObject *boss, const Common::String &name, const Common::String &domain) :
-		OptionsContainerWidget(boss, name, "AGSGameOptionsDialog", false, domain) {
+	OptionsContainerWidget(boss, name, "AGSGameOptionsDialog", false, domain) {
 
 	// Language
 	GUI::StaticTextWidget *textWidget = new GUI::StaticTextWidget(widgetsBoss(), _dialogLayout + ".translation_desc", _("Game language:"), _("Language to use for multilingual games"));
 	textWidget->setAlign(Graphics::kTextAlignRight);
 
 	_langPopUp = new GUI::PopUpWidget(widgetsBoss(), _dialogLayout + ".translation");
-	_langPopUp->appendEntry(_("<default>"), (uint32)-1);
+	_langPopUp->appendEntry(_("<default>"), (uint32) - 1);
 
 	Common::String path = ConfMan.get("path", _domain);
 	Common::FSDirectory dir(path);
@@ -128,7 +128,7 @@ void AGSOptionsWidget::load() {
 	if (!gameConfig)
 		return;
 
-	uint32 curLangIndex = (uint32)-1;
+	uint32 curLangIndex = (uint32) - 1;
 	Common::String curLang;
 	gameConfig->tryGetVal("translation", curLang);
 	if (!curLang.empty()) {
@@ -250,8 +250,8 @@ ADDetectedGame AGSMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 
 		Common::String filename = file->getName();
 		if (!filename.hasSuffixIgnoreCase(".exe") &&
-				!filename.hasSuffixIgnoreCase(".ags") &&
-				!filename.equalsIgnoreCase("ac2game.dat"))
+		        !filename.hasSuffixIgnoreCase(".ags") &&
+		        !filename.equalsIgnoreCase("ac2game.dat"))
 			// Neither, so move on
 			continue;
 
@@ -266,9 +266,9 @@ ADDetectedGame AGSMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 
 			// Check whether the game is in the detection list with a different filename
 			for (const ::AGS::AGSGameDescription *gameP = ::AGS::GAME_DESCRIPTIONS;
-				gameP->desc.gameId; ++gameP) {
+			        gameP->desc.gameId; ++gameP) {
 				if (_md5 == gameP->desc.filesDescriptions[0].md5 &&
-					f.size() == gameP->desc.filesDescriptions[0].fileSize) {
+				        f.size() == gameP->desc.filesDescriptions[0].fileSize) {
 					hasUnknownFiles = false;
 					_gameid = gameP->desc.gameId;
 					break;
diff --git a/engines/ags/engine/ac/asset_helper.h b/engines/ags/engine/ac/asset_helper.h
index 8616507be4..c2429cfd81 100644
--- a/engines/ags/engine/ac/asset_helper.h
+++ b/engines/ags/engine/ac/asset_helper.h
@@ -26,8 +26,8 @@
 //
 //=============================================================================
 
-#ifndef AGS_ENGINE_AC_ASSETHELPER_H
-#define AGS_ENGINE_AC_ASSETHELPER_H
+#ifndef AGS_ENGINE_AC_ASSET_HELPER_H
+#define AGS_ENGINE_AC_ASSET_HELPER_H
 
 #include "ags/lib/std/memory.h"
 #include "ags/lib/std/utility.h"
@@ -46,25 +46,27 @@ using AGS::Shared::String;
 
 // Looks for valid asset library everywhere and returns path, or empty string if failed
 String  find_assetlib(const String &filename);
-// Looks up for known valid asset library and returns path, or empty string if failed
-String  get_known_assetlib(const String &filename);
-// Looks for asset everywhere and returns opened stream, or NULL if failed
-Stream *find_open_asset(const String &filename);
 
 extern "C" {
 	struct PACKFILE; // Allegro 4's own stream type
 }
 
-// AssetPath combines asset library and item names
-// TODO: implement support for registering multiple libraries at once for
-// the AssetManager, then we could remove assetlib parameter.
-typedef std::pair<String, String> AssetPath;
+// AssetPath combines asset name and optional library filter, that serves to narrow down the search
+struct AssetPath {
+	String Name;
+	String Filter;
+
+	AssetPath(const String &name = "", const String &filter = "") : Name(name), Filter(filter) {
+	}
+};
 
 // Returns the path to the audio asset, considering the given bundling type
 AssetPath get_audio_clip_assetpath(int bundling_type, const String &filename);
 // Returns the path to the voice-over asset
 AssetPath get_voice_over_assetpath(const String &filename);
 
+// Locates asset among known locations, on success returns open stream and asset's size.
+Stream *LocateAsset(const AssetPath &path, size_t &asset_size);
 // Custom AGS PACKFILE user object
 // TODO: it is preferrable to let our Stream define custom readable window instead,
 // keeping this as simple as possible for now (we may require a stream classes overhaul).
diff --git a/engines/ags/engine/ac/audiochannel.cpp b/engines/ags/engine/ac/audio_channel.cpp
similarity index 97%
rename from engines/ags/engine/ac/audiochannel.cpp
rename to engines/ags/engine/ac/audio_channel.cpp
index 33ba0c2257..d580fc72d5 100644
--- a/engines/ags/engine/ac/audiochannel.cpp
+++ b/engines/ags/engine/ac/audio_channel.cpp
@@ -20,16 +20,16 @@
  *
  */
 
-#include "ags/engine/ac/audiochannel.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/audio_channel.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_audio.h"
-#include "ags/engine/ac/dynobj/cc_audioclip.h"
+#include "ags/engine/ac/dynobj/cc_audio_clip.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/shared/game/roomstruct.h"
-#include "ags/engine/script/runtimescriptvalue.h"
+#include "ags/shared/game/room_struct.h"
+#include "ags/engine/script/runtime_script_value.h"
 #include "ags/engine/media/audio/audio_system.h"
+
 #include "ags/shared/debugging/out.h"
-#include "ags/shared/game/roomstruct.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
 #include "ags/globals.h"
@@ -38,10 +38,6 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-
-
-
-
 int AudioChannel_GetID(ScriptAudioChannel *channel) {
 	return channel->id;
 }
diff --git a/engines/ags/engine/ac/audiochannel.h b/engines/ags/engine/ac/audio_channel.h
similarity index 91%
rename from engines/ags/engine/ac/audiochannel.h
rename to engines/ags/engine/ac/audio_channel.h
index da55ffa702..dbc150f31d 100644
--- a/engines/ags/engine/ac/audiochannel.h
+++ b/engines/ags/engine/ac/audio_channel.h
@@ -20,11 +20,11 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_AUDIOCHANNEL_H
-#define AGS_ENGINE_AC_AUDIOCHANNEL_H
+#ifndef AGS_ENGINE_AC_AUDIO_CHANNEL_H
+#define AGS_ENGINE_AC_AUDIO_CHANNEL_H
 
-#include "ags/shared/ac/dynobj/scriptaudioclip.h"
-#include "ags/engine/ac/dynobj/scriptaudiochannel.h"
+#include "ags/shared/ac/dynobj/script_audio_clip.h"
+#include "ags/engine/ac/dynobj/script_audio_channel.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/audioclip.cpp b/engines/ags/engine/ac/audio_clip.cpp
similarity index 95%
rename from engines/ags/engine/ac/audioclip.cpp
rename to engines/ags/engine/ac/audio_clip.cpp
index 1706b16a79..ad2dd8526c 100644
--- a/engines/ags/engine/ac/audioclip.cpp
+++ b/engines/ags/engine/ac/audio_clip.cpp
@@ -21,13 +21,16 @@
  */
 
 #include "ags/engine/ac/asset_helper.h"
-#include "ags/engine/ac/audioclip.h"
-#include "ags/engine/ac/audiochannel.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/script/runtimescriptvalue.h"
-#include "ags/engine/script/script_runtime.h"
-#include "ags/engine/ac/dynobj/cc_audiochannel.h"
+#include "ags/engine/ac/audio_clip.h"
+#include "ags/engine/ac/audio_channel.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/script/runtime_script_value.h"
+#include "ags/engine/ac/dynobj/cc_audio_channel.h"
 #include "ags/engine/media/audio/audio_system.h"
+
+#include "ags/shared/debugging/out.h"
+#include "ags/engine/script/script_api.h"
+#include "ags/engine/script/script_runtime.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -78,10 +81,6 @@ ScriptAudioChannel *AudioClip_PlayQueued(ScriptAudioClip *clip, int priority, in
 //
 //=============================================================================
 
-#include "ags/shared/debugging/out.h"
-#include "ags/engine/script/script_api.h"
-#include "ags/engine/script/script_runtime.h"
-
 RuntimeScriptValue Sc_AudioClip_GetID(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_INT(ScriptAudioClip, AudioClip_GetID);
 }
diff --git a/engines/ags/engine/ac/audioclip.h b/engines/ags/engine/ac/audio_clip.h
similarity index 89%
rename from engines/ags/engine/ac/audioclip.h
rename to engines/ags/engine/ac/audio_clip.h
index 00d8075b97..898f1513a0 100644
--- a/engines/ags/engine/ac/audioclip.h
+++ b/engines/ags/engine/ac/audio_clip.h
@@ -20,11 +20,11 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_AUDIOCLIP_H
-#define AGS_ENGINE_AC_AUDIOCLIP_H
+#ifndef AGS_ENGINE_AC_AUDIO_CLIP_H
+#define AGS_ENGINE_AC_AUDIO_CLIP_H
 
-#include "ags/shared/ac/dynobj/scriptaudioclip.h"
-#include "ags/engine/ac/dynobj/scriptaudiochannel.h"
+#include "ags/shared/ac/dynobj/script_audio_clip.h"
+#include "ags/engine/ac/dynobj/script_audio_channel.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/button.cpp b/engines/ags/engine/ac/button.cpp
index 27aad8afd5..88ee082d9d 100644
--- a/engines/ags/engine/ac/button.cpp
+++ b/engines/ags/engine/ac/button.cpp
@@ -24,23 +24,25 @@
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/gui.h"
 #include "ags/shared/ac/view.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/string.h"
-#include "ags/engine/ac/viewframe.h"
+#include "ags/engine/ac/view_frame.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/engine/gui/animatingguibutton.h"
-#include "ags/shared/gui/guimain.h"
+#include "ags/engine/gui/animating_gui_button.h"
+#include "ags/shared/gui/gui_main.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
-#include "ags/engine/ac/dynobj/scriptstring.h"
+#include "ags/engine/ac/dynobj/script_string.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
+// *** BUTTON FUNCTIONS
+
 void Button_Animate(GUIButton *butt, int view, int loop, int speed, int repeat) {
 	int guin = butt->ParentId;
 	int objn = butt->Id;
@@ -92,7 +94,6 @@ void Button_SetText(GUIButton *butt, const char *newtx) {
 	newtx = get_translation(newtx);
 
 	if (strcmp(butt->GetText(), newtx)) {
-		_G(guis_need_update) = 1;
 		butt->SetText(newtx);
 	}
 }
@@ -103,7 +104,7 @@ void Button_SetFont(GUIButton *butt, int newFont) {
 
 	if (butt->Font != newFont) {
 		butt->Font = newFont;
-		_G(guis_need_update) = 1;
+		butt->NotifyParentChanged();
 	}
 }
 
@@ -118,7 +119,6 @@ int Button_GetClipImage(GUIButton *butt) {
 void Button_SetClipImage(GUIButton *butt, int newval) {
 	if (butt->IsClippingImage() != (newval != 0)) {
 		butt->SetClipImage(newval != 0);
-		_G(guis_need_update) = 1;
 	}
 }
 
@@ -140,7 +140,7 @@ void Button_SetMouseOverGraphic(GUIButton *guil, int slotn) {
 		guil->CurrentImage = slotn;
 	guil->MouseOverImage = slotn;
 
-	_G(guis_need_update) = 1;
+	guil->NotifyParentChanged();
 	FindAndRemoveButtonAnimation(guil->ParentId, guil->Id);
 }
 
@@ -154,18 +154,16 @@ void Button_SetNormalGraphic(GUIButton *guil, int slotn) {
 	if (((guil->IsMouseOver == 0) || (guil->MouseOverImage < 1)) && (guil->IsPushed == 0))
 		guil->CurrentImage = slotn;
 	guil->Image = slotn;
-
-	// WORKAROUND: Showing the map in Shivah has a button with invalid slot -1
-	if (slotn == -1) {
+	// update the clickable area to the same size as the graphic
+	if (slotn < 0 || (size_t)slotn >= _GP(game).SpriteInfos.size()) {
 		guil->Width = 0;
 		guil->Height = 0;
 	} else {
-		// update the clickable area to the same size as the graphic
 		guil->Width = _GP(game).SpriteInfos[slotn].Width;
 		guil->Height = _GP(game).SpriteInfos[slotn].Height;
 	}
 
-	_G(guis_need_update) = 1;
+	guil->NotifyParentChanged();
 	FindAndRemoveButtonAnimation(guil->ParentId, guil->Id);
 }
 
@@ -180,7 +178,7 @@ void Button_SetPushedGraphic(GUIButton *guil, int slotn) {
 		guil->CurrentImage = slotn;
 	guil->PushedImage = slotn;
 
-	_G(guis_need_update) = 1;
+	guil->NotifyParentChanged();
 	FindAndRemoveButtonAnimation(guil->ParentId, guil->Id);
 }
 
@@ -191,7 +189,7 @@ int Button_GetTextColor(GUIButton *butt) {
 void Button_SetTextColor(GUIButton *butt, int newcol) {
 	if (butt->TextColor != newcol) {
 		butt->TextColor = newcol;
-		_G(guis_need_update) = 1;
+		butt->NotifyParentChanged();
 	}
 }
 
@@ -216,7 +214,7 @@ int UpdateAnimatingButton(int bu) {
 			_G(animbuts)[bu].frame = 0;
 			// multi-loop anim, go back
 			while ((_G(animbuts)[bu].loop > 0) &&
-				(tview->loops[_G(animbuts)[bu].loop - 1].RunNextLoop()))
+			        (tview->loops[_G(animbuts)[bu].loop - 1].RunNextLoop()))
 				_G(animbuts)[bu].loop--;
 		} else
 			return 1;
@@ -229,7 +227,7 @@ int UpdateAnimatingButton(int bu) {
 	_GP(guibuts)[_G(animbuts)[bu].buttonid].CurrentImage = _GP(guibuts)[_G(animbuts)[bu].buttonid].Image;
 	_GP(guibuts)[_G(animbuts)[bu].buttonid].PushedImage = 0;
 	_GP(guibuts)[_G(animbuts)[bu].buttonid].MouseOverImage = 0;
-	_G(guis_need_update) = 1;
+	_GP(guibuts)[_G(animbuts)[bu].buttonid].NotifyParentChanged();
 
 	_G(animbuts)[bu].wait = _G(animbuts)[bu].speed + tview->loops[_G(animbuts)[bu].loop].frames[_G(animbuts)[bu].frame].speed;
 	return 0;
@@ -292,7 +290,7 @@ int Button_GetTextAlignment(GUIButton *butt) {
 void Button_SetTextAlignment(GUIButton *butt, int align) {
 	if (butt->TextAlignment != align) {
 		butt->TextAlignment = (FrameAlignment)align;
-		_G(guis_need_update) = 1;
+		butt->NotifyParentChanged();
 	}
 }
 
@@ -302,8 +300,6 @@ void Button_SetTextAlignment(GUIButton *butt, int align) {
 //
 //=============================================================================
 
-
-
 // void | GUIButton *butt, int view, int loop, int speed, int repeat
 RuntimeScriptValue Sc_Button_Animate(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_VOID_PINT4(GUIButton, Button_Animate);
diff --git a/engines/ags/engine/ac/button.h b/engines/ags/engine/ac/button.h
index 64215f89fd..1eb49ace33 100644
--- a/engines/ags/engine/ac/button.h
+++ b/engines/ags/engine/ac/button.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_BUTTON_H
 #define AGS_ENGINE_AC_BUTTON_H
 
-#include "ags/shared/gui/guibutton.h"
+#include "ags/shared/gui/gui_button.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/cdaudio.cpp b/engines/ags/engine/ac/cd_audio.cpp
similarity index 89%
rename from engines/ags/engine/ac/cdaudio.cpp
rename to engines/ags/engine/ac/cd_audio.cpp
index f4c541c8fd..601bde638c 100644
--- a/engines/ags/engine/ac/cdaudio.cpp
+++ b/engines/ags/engine/ac/cd_audio.cpp
@@ -20,8 +20,8 @@
  *
  */
 
-#include "ags/engine/ac/cdaudio.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
+#include "ags/engine/ac/cd_audio.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -37,7 +37,7 @@ int cd_manager(int cmdd, int datt) {
 		init_cd_player();
 	}
 	if (cmdd == 0) return _G(use_cdplayer);
-	if (_G(use_cdplayer) == 0) return 0; // ignore other commands
+	if (_G(use_cdplayer) == 0) return 0;  // ignore other commands
 
 	return _G(platform)->CDPlayerCommand(cmdd, datt);
 }
diff --git a/engines/ags/engine/ac/cdaudio.h b/engines/ags/engine/ac/cd_audio.h
similarity index 100%
rename from engines/ags/engine/ac/cdaudio.h
rename to engines/ags/engine/ac/cd_audio.h
diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 2c36d9f145..ce14504554 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -28,7 +28,7 @@
 
 #include "ags/engine/ac/character.h"
 #include "ags/shared/ac/common.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/shared/ac/view.h"
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
@@ -42,45 +42,44 @@
 #include "ags/engine/ac/global_room.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/gui.h"
-#include "ags/engine/ac/lipsync.h"
+#include "ags/engine/ac/lip_sync.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/ac/object.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/properties.h"
 #include "ags/engine/ac/room.h"
-#include "ags/engine/ac/screenoverlay.h"
+#include "ags/engine/ac/screen_overlay.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/ac/system.h"
-#include "ags/engine/ac/viewframe.h"
-#include "ags/engine/ac/walkablearea.h"
-#include "ags/shared/gui/guimain.h"
+#include "ags/engine/ac/view_frame.h"
+#include "ags/engine/ac/walkable_area.h"
+#include "ags/shared/gui/gui_main.h"
 #include "ags/engine/ac/route_finder.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/engine/main/game_run.h"
 #include "ags/engine/main/update.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/shared/util/string_compat.h"
-#include "ags/engine/gfx/graphicsdriver.h"
-#include "ags/engine/script/runtimescriptvalue.h"
+#include "ags/lib/std/math.h"
+#include "ags/engine/gfx/graphics_driver.h"
+#include "ags/engine/script/runtime_script_value.h"
 #include "ags/engine/ac/dynobj/cc_character.h"
 #include "ags/engine/ac/dynobj/cc_inventory.h"
 #include "ags/engine/script/script_runtime.h"
 #include "ags/shared/gfx/gfx_def.h"
 #include "ags/engine/media/audio/audio_system.h"
-#include "ags/engine/ac/movelist.h"
+#include "ags/engine/ac/move_list.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
-#include "ags/engine/ac/dynobj/scriptstring.h"
+#include "ags/engine/ac/dynobj/script_string.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
-// **** CHARACTER: FUNCTIONS ****
-
 void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addIndex) {
 	int ee;
 
@@ -123,10 +122,9 @@ void Character_AddInventory(CharacterInfo *chaa, ScriptInvItem *invi, int addInd
 		_G(charextra)[charid].invorder[addIndex] = inum;
 	}
 	_G(charextra)[charid].invorder_count++;
-	_G(guis_need_update) = 1;
+	GUI::MarkInventoryForUpdate(charid, charid == _GP(game).playercharacter);
 	if (chaa == _G(playerchar))
 		run_on_event(GE_ADD_INV, RuntimeScriptValue().SetInt32(inum));
-
 }
 
 void Character_AddWaypoint(CharacterInfo *chaa, int x, int y) {
@@ -226,17 +224,19 @@ void Character_ChangeRoomSetLoop(CharacterInfo *chaa, int room, int x, int y, in
 	}
 
 	if ((x != SCR_NO_VALUE) && (y != SCR_NO_VALUE)) {
-		// We cannot set character position right away,
-		// because room switch will occur only after the script end,
-		// and character position may be still changing meanwhile.
 		_G(new_room_pos) = 0;
 
-		// Don't check X or Y bounds, so that they can do a
-		// walk-in animation if they want
-		_G(new_room_x) = x;
-		_G(new_room_y) = y;
-		if (direction != SCR_NO_VALUE)
-			_G(new_room_loop) = direction;
+		if (_G(loaded_game_file_version) <= kGameVersion_272) {
+			// Set position immediately on 2.x.
+			chaa->x = x;
+			chaa->y = y;
+		} else {
+			// don't check X or Y bounds, so that they can do a
+			// walk-in animation if they want
+			_G(new_room_x) = x;
+			_G(new_room_y) = y;
+			if (direction != SCR_NO_VALUE) _G(new_room_loop) = direction;
+		}
 	}
 
 	NewRoom(room);
@@ -663,7 +663,7 @@ void Character_LoseInventory(CharacterInfo *chap, ScriptInvItem *invi) {
 			}
 		}
 	}
-	_G(guis_need_update) = 1;
+	GUI::MarkInventoryForUpdate(charid, charid == _GP(game).playercharacter);
 
 	if (chap == _G(playerchar))
 		run_on_event(GE_LOSE_INV, RuntimeScriptValue().SetInt32(inum));
@@ -705,7 +705,7 @@ void Character_SayAt(CharacterInfo *chaa, int x, int y, int width, const char *t
 
 ScriptOverlay *Character_SayBackground(CharacterInfo *chaa, const char *texx) {
 
-	int ovltype = DisplaySpeechBackground(chaa->index_id, (const char *)texx);
+	int ovltype = DisplaySpeechBackground(chaa->index_id, texx);
 	int ovri = find_overlay_of_type(ovltype);
 	if (ovri < 0)
 		quit("!SayBackground internal error: no overlay");
@@ -1030,8 +1030,6 @@ ScriptInvItem *Character_GetActiveInventory(CharacterInfo *chaa) {
 }
 
 void Character_SetActiveInventory(CharacterInfo *chaa, ScriptInvItem *iit) {
-	_G(guis_need_update) = 1;
-
 	if (iit == nullptr) {
 		chaa->activeinv = -1;
 
@@ -1040,6 +1038,7 @@ void Character_SetActiveInventory(CharacterInfo *chaa, ScriptInvItem *iit) {
 			if (GetCursorMode() == MODE_USE)
 				set_cursor_mode(0);
 		}
+		GUI::MarkInventoryForUpdate(chaa->index_id, chaa->index_id == _GP(game).playercharacter);
 		return;
 	}
 
@@ -1055,6 +1054,7 @@ void Character_SetActiveInventory(CharacterInfo *chaa, ScriptInvItem *iit) {
 		update_inv_cursor(iit->id);
 		set_cursor_mode(MODE_USE);
 	}
+	GUI::MarkInventoryForUpdate(chaa->index_id, chaa->index_id == _GP(game).playercharacter);
 }
 
 int Character_GetAnimating(CharacterInfo *chaa) {
@@ -1543,6 +1543,8 @@ void Character_SetZ(CharacterInfo *chaa, int newval) {
 	chaa->z = newval;
 }
 
+
+
 int Character_GetSpeakingFrame(CharacterInfo *chaa) {
 
 	if ((_G(face_talking) >= 0) && (_G(facetalkrepeat))) {
@@ -1562,7 +1564,7 @@ int Character_GetSpeakingFrame(CharacterInfo *chaa) {
 //=============================================================================
 
 // order of loops to turn character in circle from down to down
-const int turnlooporder[8] = {0, 6, 1, 7, 3, 5, 2, 4};
+int turnlooporder[8] = {0, 6, 1, 7, 3, 5, 2, 4};
 
 void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims) {
 	CharacterInfo *chin = &_GP(game).chars[chac];
@@ -1809,7 +1811,7 @@ int doNextCharMoveStep(CharacterInfo *chi, int &char_index, CharacterExtras *che
 	return 0;
 }
 
-int find_nearest_walkable_area_within(int32_t *xx, int32_t *yy, int range, int step) {
+int find_nearest_walkable_area_within(int *xx, int *yy, int range, int step) {
 	int ex, ey, nearest = 99999, thisis, nearx = 0, neary = 0;
 	int startx = 0, starty = 14;
 	int roomWidthLowRes = room_to_mask_coord(_GP(thisroom).Width);
@@ -1867,7 +1869,7 @@ int find_nearest_walkable_area_within(int32_t *xx, int32_t *yy, int range, int s
 	return 0;
 }
 
-void find_nearest_walkable_area(int32_t *xx, int32_t *yy) {
+void find_nearest_walkable_area(int *xx, int *yy) {
 
 	int pixValue = _GP(thisroom).WalkAreaMask->GetPixel(room_to_mask_coord(xx[0]), room_to_mask_coord(yy[0]));
 	// only fix this code if the game was built with 2.61 or above
@@ -2242,7 +2244,7 @@ void _DisplayThoughtCore(int chid, const char *displbuf) {
 		ypp = -1;
 	}
 
-	_displayspeech((const char *)displbuf, chid, xpp, ypp, width, 1);
+	_displayspeech(displbuf, chid, xpp, ypp, width, 1);
 }
 
 void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int isThought) {
@@ -2262,13 +2264,14 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 
 	_G(said_speech_line) = 1;
 
+	int aa;
 	if (_GP(play).bgspeech_stay_on_display == 0) {
 		// remove any background speech
-		for (size_t i = 0; i < _GP(screenover).size();) {
-			if (_GP(screenover)[i].timeout > 0)
-				remove_screen_overlay(_GP(screenover)[i].type);
-			else
-				i++;
+		for (aa = 0; aa < _G(numscreenover); aa++) {
+			if (_GP(screenover)[aa].timeout > 0) {
+				remove_screen_overlay(_GP(screenover)[aa].type);
+				aa--;
+			}
 		}
 	}
 	_G(said_text) = 1;
@@ -2279,7 +2282,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 
 	int isPause = 1;
 	// if the message is all .'s, don't display anything
-	for (int aa = 0; texx[aa] != 0; aa++) {
+	for (aa = 0; texx[aa] != 0; aa++) {
 		if (texx[aa] != '.') {
 			isPause = 0;
 			break;
@@ -2384,12 +2387,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 		if ((speakingChar->view < 0) ||
 		        (speakingChar->loop >= _G(views)[speakingChar->view].numLoops) ||
 		        (_G(views)[speakingChar->view].loops[speakingChar->loop].numFrames < 1)) {
-#if AGS_PLATFORM_SCUMMVM
-			// WORKAROUND: Fix crash in Fatman intro by ignoring invalid speeches
-			return;
-#else
 			quitprintf("Unable to display speech because the character %s has an invalid view frame (View %d, loop %d, frame %d)", speakingChar->scrname, speakingChar->view + 1, speakingChar->loop, speakingChar->frame);
-#endif
 		}
 
 		_G(our_eip) = 1504;
@@ -2630,12 +2628,7 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 			if (speakingChar->on && // don't bother checking if character is not visible (also fixes 'Trilby's Notes' legacy game)
 			        ((speakingChar->loop >= _G(views)[speakingChar->view].numLoops) ||
 			         (_G(views)[speakingChar->view].loops[speakingChar->loop].numFrames < 1))) {
-#if AGS_PLATFORM_SCUMMVM
-				// WORKAROUND: Fix crash in Fatman intro by ignoring invalid speeches
-				return;
-#else
 				quitprintf("!Unable to display speech because the character %s has an invalid speech view (View %d, loop %d, frame %d)", speakingChar->scrname, speakingChar->view + 1, speakingChar->loop, speakingChar->frame);
-#endif
 			}
 
 			// set up the speed of the first frame
@@ -2814,8 +2807,6 @@ PViewport FindNearestViewport(int charid) {
 //
 //=============================================================================
 
-
-
 // void | CharacterInfo *chaa, ScriptInvItem *invi, int addIndex
 RuntimeScriptValue Sc_Character_AddInventory(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_VOID_POBJ_PINT(CharacterInfo, Character_AddInventory, ScriptInvItem);
diff --git a/engines/ags/engine/ac/character.h b/engines/ags/engine/ac/character.h
index 9f145294bf..7619cfc1e7 100644
--- a/engines/ags/engine/ac/character.h
+++ b/engines/ags/engine/ac/character.h
@@ -23,11 +23,11 @@
 #ifndef AGS_ENGINE_AC_CHARACTER_H
 #define AGS_ENGINE_AC_CHARACTER_H
 
-#include "ags/shared/ac/characterinfo.h"
-#include "ags/engine/ac/characterextras.h"
-#include "ags/engine/ac/dynobj/scriptobject.h"
-#include "ags/engine/ac/dynobj/scriptinvitem.h"
-#include "ags/engine/ac/dynobj/scriptoverlay.h"
+#include "ags/shared/ac/character_info.h"
+#include "ags/engine/ac/character_extras.h"
+#include "ags/engine/ac/dynobj/script_object.h"
+#include "ags/engine/ac/dynobj/script_inv_item.h"
+#include "ags/engine/ac/dynobj/script_overlay.h"
 #include "ags/engine/game/viewport.h"
 #include "ags/shared/util/geometry.h"
 
@@ -184,8 +184,8 @@ void fix_player_sprite(MoveList *cmls, CharacterInfo *chinf);
 // Check whether two characters have walked into each other
 int  has_hit_another_character(int sourceChar);
 int  doNextCharMoveStep(CharacterInfo *chi, int &char_index, CharacterExtras *chex);
-int  find_nearest_walkable_area_within(int32_t *xx, int32_t *yy, int range, int step);
-void find_nearest_walkable_area(int32_t *xx, int32_t *yy);
+int  find_nearest_walkable_area_within(int *xx, int *yy, int range, int step);
+void find_nearest_walkable_area(int *xx, int *yy);
 void walk_character(int chac, int tox, int toy, int ignwal, bool autoWalkAnims);
 void FindReasonableLoopForCharacter(CharacterInfo *chap);
 void walk_or_move_character(CharacterInfo *chaa, int x, int y, int blocking, int direct, bool isWalk);
@@ -220,7 +220,7 @@ Rect GetCharacterRoomBBox(int charid, bool use_frame_0 = false);
 PViewport FindNearestViewport(int charid);
 
 // order of loops to turn character in circle from down to down
-extern const int turnlooporder[8];
+extern int turnlooporder[8];
 
 } // namespace AGS3
 
diff --git a/engines/ags/engine/ac/charactercache.h b/engines/ags/engine/ac/character_cache.h
similarity index 94%
rename from engines/ags/engine/ac/charactercache.h
rename to engines/ags/engine/ac/character_cache.h
index 1b1810fb4f..3a96612278 100644
--- a/engines/ags/engine/ac/charactercache.h
+++ b/engines/ags/engine/ac/character_cache.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_CHARACTERCACHE_H
-#define AGS_ENGINE_AC_CHARACTERCACHE_H
+#ifndef AGS_ENGINE_AC_CHARACTER_CACHE_H
+#define AGS_ENGINE_AC_CHARACTER_CACHE_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/characterextras.cpp b/engines/ags/engine/ac/character_extras.cpp
similarity index 97%
rename from engines/ags/engine/ac/characterextras.cpp
rename to engines/ags/engine/ac/character_extras.cpp
index 2fec603b6d..100d806064 100644
--- a/engines/ags/engine/ac/characterextras.cpp
+++ b/engines/ags/engine/ac/character_extras.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/characterextras.h"
+#include "ags/engine/ac/character_extras.h"
 #include "ags/shared/util/stream.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/characterextras.h b/engines/ags/engine/ac/character_extras.h
similarity index 94%
rename from engines/ags/engine/ac/characterextras.h
rename to engines/ags/engine/ac/character_extras.h
index 67e6e568c2..88f55db89e 100644
--- a/engines/ags/engine/ac/characterextras.h
+++ b/engines/ags/engine/ac/character_extras.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_CHARACTEREXTRAS_H
-#define AGS_ENGINE_AC_CHARACTEREXTRAS_H
+#ifndef AGS_ENGINE_AC_CHARACTER_EXTRAS_H
+#define AGS_ENGINE_AC_CHARACTER_EXTRAS_H
 
 #include "ags/engine/ac/runtime_defines.h"
 
@@ -31,9 +31,8 @@ namespace AGS3 {
 namespace AGS {
 namespace Shared {
 class Stream;
-} // namespace Shared
-} // namespace AGS
-
+}
+}
 using namespace AGS; // FIXME later
 
 struct CharacterExtras {
diff --git a/engines/ags/engine/ac/characterinfo_engine.cpp b/engines/ags/engine/ac/character_info_engine.cpp
similarity index 90%
rename from engines/ags/engine/ac/characterinfo_engine.cpp
rename to engines/ags/engine/ac/character_info_engine.cpp
index 5bf469a910..3fc262c0c6 100644
--- a/engines/ags/engine/ac/characterinfo_engine.cpp
+++ b/engines/ags/engine/ac/character_info_engine.cpp
@@ -20,22 +20,22 @@
  *
  */
 
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/shared/ac/common.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/character.h"
-#include "ags/engine/ac/characterextras.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/character_extras.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/math.h"
-#include "ags/engine/ac/viewframe.h"
+#include "ags/engine/ac/view_frame.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/shared/game/roomstruct.h"
-#include "ags/engine/main/maindefines_ex.h"    // RETURN_CONTINUE
+#include "ags/shared/game/room_struct.h"
+#include "ags/engine/main/main_defines_ex.h"    // RETURN_CONTINUE
 #include "ags/engine/main/update.h"
 #include "ags/engine/media/audio/audio_system.h"
-#include "ags/globals.h"
 #include "ags/ags.h"
+#include "ags/globals.h"
 
 namespace AGS3 {
 
@@ -131,8 +131,8 @@ int CharacterInfo::update_character_walking(CharacterExtras *chex) {
 				if (wantloop < 0)
 					wantloop = 7;
 				if ((turnlooporder[wantloop] >= _G(views)[view].numLoops) ||
-					(_G(views)[view].loops[turnlooporder[wantloop]].numFrames < 1) ||
-					((turnlooporder[wantloop] >= 4) && ((flags & CHF_NODIAGONAL) != 0))) {
+				        (_G(views)[view].loops[turnlooporder[wantloop]].numFrames < 1) ||
+				        ((turnlooporder[wantloop] >= 4) && ((flags & CHF_NODIAGONAL) != 0))) {
 					if (walking >= TURNING_BACKWARDS)
 						wantloop--;
 					else
@@ -186,8 +186,8 @@ void CharacterInfo::update_character_moving(int &char_index, CharacterExtras *ch
 				// to stop it being jumpy
 				chex->xwas = x;
 				chex->ywas = y;
-				x = ((x)-oldxp) / 2 + oldxp;
-				y = ((y)-oldyp) / 2 + oldyp;
+				x = ((x) - oldxp) / 2 + oldxp;
+				y = ((y) - oldyp) / 2 + oldyp;
 			} else if (numSteps > 0)
 				chex->xwas = INVALID_X;
 
@@ -252,8 +252,8 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
 	// not moving, but animating
 	// idleleft is <0 while idle view is playing (.animating is 0)
 	if (((animating != 0) || (idleleft < 0)) &&
-		((walking == 0) || ((flags & CHF_MOVENOTWALK) != 0)) &&
-		(room == _G(displayed_room))) {
+	        ((walking == 0) || ((flags & CHF_MOVENOTWALK) != 0)) &&
+	        (room == _G(displayed_room))) {
 		doing_nothing = 0;
 		// idle anim doesn't count as doing something
 		if (idleleft < 0)
@@ -267,7 +267,7 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
 			// closed mouth at end of sentence
 			// NOTE: standard lip-sync is synchronized with text timer, not voice file
 			if (_GP(play).speech_in_post_state ||
-				((_GP(play).messagetime >= 0) && (_GP(play).messagetime < _GP(play).close_mouth_speech_time)))
+			        ((_GP(play).messagetime >= 0) && (_GP(play).messagetime < _GP(play).close_mouth_speech_time)))
 				frame = 0;
 
 			if (frame != fraa) {
@@ -284,7 +284,7 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
 				if (frame < 0) {
 					// if the previous loop is a Run Next Loop one, go back to it
 					if ((loop > 0) &&
-						(_G(views)[view].loops[loop - 1].RunNextLoop())) {
+					        (_G(views)[view].loops[loop - 1].RunNextLoop())) {
 
 						loop--;
 						frame = _G(views)[view].loops[loop].numFrames - 1;
@@ -305,10 +305,10 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
 				frame++;
 
 			if ((aa == _G(char_speaking)) &&
-				(_GP(play).speech_in_post_state ||
-				((!_GP(play).speech_has_voice) &&
-					(_GP(play).close_mouth_speech_time > 0) &&
-					(_GP(play).messagetime < _GP(play).close_mouth_speech_time)))) {
+			        (_GP(play).speech_in_post_state ||
+			         ((!_GP(play).speech_has_voice) &&
+			          (_GP(play).close_mouth_speech_time > 0) &&
+			          (_GP(play).messagetime < _GP(play).close_mouth_speech_time)))) {
 				// finished talking - stop animation
 				animating = 0;
 				frame = 0;
@@ -340,7 +340,7 @@ int CharacterInfo::update_character_animating(int &aa, int &doing_nothing) {
 					// if it's a multi-loop animation, go back to start
 					if (_GP(play).no_multiloop_repeat == 0) {
 						while ((loop > 0) &&
-							(_G(views)[view].loops[loop - 1].RunNextLoop()))
+						        (_G(views)[view].loops[loop - 1].RunNextLoop()))
 							loop--;
 					}
 				}
@@ -386,7 +386,7 @@ void CharacterInfo::update_character_follower(int &aa, int &numSheep, int *follo
 		else if (Random(100) < (followinfo & 0x00ff));
 		// the followed character has changed room
 		else if ((room != _GP(game).chars[following].room)
-			&& (_GP(game).chars[following].on == 0))
+		         && (_GP(game).chars[following].on == 0))
 			;  // do nothing if the player isn't visible
 		else if (room != _GP(game).chars[following].room) {
 			prevroom = room;
@@ -421,15 +421,15 @@ void CharacterInfo::update_character_follower(int &aa, int &numSheep, int *follo
 			// if the characetr is following another character and
 			// neither is in the current room, don't try to move
 		} else if ((abs(_GP(game).chars[following].x - x) > distaway + 30) |
-			(abs(_GP(game).chars[following].y - y) > distaway + 30) |
-			((followinfo & 0x00ff) == 0)) {
+		           (abs(_GP(game).chars[following].y - y) > distaway + 30) |
+		           ((followinfo & 0x00ff) == 0)) {
 			// in same room
 			int goxoffs = (Random(50) - 25);
 			// make sure he's not standing on top of the other man
 			if (goxoffs < 0) goxoffs -= distaway;
 			else goxoffs += distaway;
 			walk_character(aa, _GP(game).chars[following].x + goxoffs,
-				_GP(game).chars[following].y + (Random(50) - 25), 0, true);
+			               _GP(game).chars[following].y + (Random(50) - 25), 0, true);
 			doing_nothing = 0;
 		}
 	}
@@ -474,7 +474,7 @@ void CharacterInfo::update_character_idle(CharacterExtras *chex, int &doing_noth
 				useloop = 0;
 
 			animate_character(this, useloop,
-				animspeed + 5, (idletime == 0) ? 1 : 0, 1);
+			                  animspeed + 5, (idletime == 0) ? 1 : 0, 1);
 
 			// don't set Animating while the idle anim plays
 			animating = 0;
diff --git a/engines/ags/engine/ac/datetime.cpp b/engines/ags/engine/ac/date_time.cpp
similarity index 97%
rename from engines/ags/engine/ac/datetime.cpp
rename to engines/ags/engine/ac/date_time.cpp
index 0c8c0af3c5..b608fe1eb5 100644
--- a/engines/ags/engine/ac/datetime.cpp
+++ b/engines/ags/engine/ac/date_time.cpp
@@ -20,9 +20,9 @@
  *
  */
 
-#include "ags/engine/ac/datetime.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
-#include "ags/engine/script/runtimescriptvalue.h"
+#include "ags/engine/ac/date_time.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
+#include "ags/engine/script/runtime_script_value.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
diff --git a/engines/ags/engine/ac/datetime.h b/engines/ags/engine/ac/date_time.h
similarity index 96%
rename from engines/ags/engine/ac/datetime.h
rename to engines/ags/engine/ac/date_time.h
index 8711739518..a7fcd123d5 100644
--- a/engines/ags/engine/ac/datetime.h
+++ b/engines/ags/engine/ac/date_time.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DATETIME_H
 #define AGS_ENGINE_AC_DATETIME_H
 
-#include "ags/engine/ac/dynobj/scriptdatetime.h"
+#include "ags/engine/ac/dynobj/script_date_time.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index c4cd66b896..a5354a2e7d 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -23,12 +23,12 @@
 #include "ags/engine/ac/dialog.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/character.h"
-#include "ags/shared/ac/characterinfo.h"
-#include "ags/shared/ac/dialogtopic.h"
+#include "ags/shared/ac/character_info.h"
+#include "ags/shared/ac/dialog_topic.h"
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/engine/ac/gamestate.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/engine/ac/game_state.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_dialog.h"
 #include "ags/engine/ac/global_display.h"
@@ -36,35 +36,35 @@
 #include "ags/engine/ac/global_gui.h"
 #include "ags/engine/ac/global_room.h"
 #include "ags/engine/ac/global_translation.h"
-#include "ags/engine/ac/keycode.h"
+#include "ags/shared/ac/keycode.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/ac/parser.h"
 #include "ags/engine/ac/sys_events.h"
 #include "ags/engine/ac/string.h"
-#include "ags/engine/ac/dynobj/scriptdialogoptionsrendering.h"
-#include "ags/engine/ac/dynobj/scriptdrawingsurface.h"
+#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
+#include "ags/engine/ac/dynobj/script_drawing_surface.h"
 #include "ags/engine/ac/system.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/shared/font/fonts.h"
 #include "ags/engine/script/cc_instance.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/shared/gui/guitextbox.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/shared/gui/gui_textbox.h"
 #include "ags/engine/main/game_run.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/engine/script/script.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/gfx/ddb.h"
 #include "ags/engine/gfx/gfx_util.h"
-#include "ags/engine/gfx/graphicsdriver.h"
+#include "ags/engine/gfx/graphics_driver.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/media/audio/audio_system.h"
+
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
-#include "ags/engine/ac/dynobj/scriptstring.h"
+#include "ags/engine/ac/dynobj/script_string.h"
 #include "ags/globals.h"
-#include "ags/ags.h"
 
 namespace AGS3 {
 
@@ -305,8 +305,8 @@ int run_dialog_script(DialogTopic *dtpp, int dialogID, int offse, int optionInde
 }
 
 int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, int numdisp, int mouseison, int areawid,
-						 int bullet_wid, int usingfont, DialogTopic *dtop, char *disporder, short *dispyp,
-						 int linespacing, int utextcol, int padding) {
+                         int bullet_wid, int usingfont, DialogTopic *dtop, char *disporder, short *dispyp,
+                         int linespacing, int utextcol, int padding) {
 	int ww;
 
 	color_t text_color;
@@ -327,7 +327,7 @@ int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, in
 			else text_color = ds->GetCompatibleColor(utextcol);
 		}
 
-		break_up_text_into_lines(get_translation(dtop->optionnames[(int)disporder[ww]]), _GP(fontLines), areawid - (2 * padding + 2 + bullet_wid), usingfont);
+		break_up_text_into_lines(get_translation(dtop->optionnames[(int)disporder[ww]]), Lines, areawid - (2 * padding + 2 + bullet_wid), usingfont);
 		dispyp[ww] = curyp;
 		if (_GP(game).dialog_bullet > 0) {
 			draw_gui_sprite_v330(ds, _GP(game).dialog_bullet, dlgxp, curyp, ds_has_alpha);
@@ -341,8 +341,8 @@ int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, in
 			sprintf(tempbfr, "%d.", ww + 1);
 			wouttext_outline(ds, dlgxp + actualpicwid, curyp, usingfont, text_color, tempbfr);
 		}
-		for (size_t cc = 0; cc < _GP(fontLines).Count(); cc++) {
-			wouttext_outline(ds, dlgxp + ((cc == 0) ? 0 : 9) + bullet_wid, curyp, usingfont, text_color, _GP(fontLines)[cc]);
+		for (size_t cc = 0; cc < Lines.Count(); cc++) {
+			wouttext_outline(ds, dlgxp + ((cc == 0) ? 0 : 9) + bullet_wid, curyp, usingfont, text_color, Lines[cc]);
 			curyp += linespacing;
 		}
 		if (ww < numdisp - 1)
@@ -356,8 +356,8 @@ int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, in
 #define GET_OPTIONS_HEIGHT {\
 		needheight = 0;\
 		for (int i = 0; i < numdisp; ++i) {\
-			break_up_text_into_lines(get_translation(dtop->optionnames[(int)disporder[i]]), _GP(fontLines), areawid-(2*padding+2+bullet_wid), usingfont);\
-			needheight += getheightoflines(usingfont, _GP(fontLines).Count()) + data_to_game_coord(_GP(game).options[OPT_DIALOGGAP]);\
+			break_up_text_into_lines(get_translation(dtop->optionnames[(int)disporder[i]]), Lines, areawid-(2*padding+2+bullet_wid), usingfont);\
+			needheight += getheightoflines(usingfont, Lines.Count()) + data_to_game_coord(_GP(game).options[OPT_DIALOGGAP]);\
 		}\
 		if (parserInput) needheight += parserInput->Height + data_to_game_coord(_GP(game).options[OPT_DIALOGGAP]);\
 	}
@@ -504,7 +504,10 @@ void DialogOptions::Prepare(int _dlgnum, bool _runGameLoopsInBackground) {
 }
 
 void DialogOptions::Show() {
-	if (numdisp < 1) quit("!DoDialog: all options have been turned off");
+	if (numdisp < 1) {
+		debug_script_warn("Dialog: all options have been turned off, stopping dialog.");
+		return;
+	}
 	// Don't display the options if there is only one and the parser
 	// is not enabled.
 	if (!((numdisp > 1) || (parserInput != nullptr) || (_GP(play).show_single_dialog_option))) {
@@ -587,8 +590,7 @@ void DialogOptions::Show() {
 	update_polled_stuff_if_runtime();
 
 	Redraw();
-	while (Run() && !SHOULD_QUIT) {
-	}
+	while (Run());
 
 	if (!_GP(play).mouse_cursor_hidden)
 		ags_domouse(DOMOUSE_DISABLE);
@@ -639,7 +641,7 @@ void DialogOptions::Redraw() {
 		int biggest = 0;
 		padding = _GP(guis)[_GP(game).options[OPT_DIALOGIFACE]].Padding;
 		for (int i = 0; i < numdisp; ++i) {
-			break_up_text_into_lines(get_translation(dtop->optionnames[(int)disporder[i]]), _GP(fontLines), areawid - ((2 * padding + 2) + bullet_wid), usingfont);
+			break_up_text_into_lines(get_translation(dtop->optionnames[(int)disporder[i]]), Lines, areawid - ((2 * padding + 2) + bullet_wid), usingfont);
 			if (_G(longestline) > biggest)
 				biggest = _G(longestline);
 		}
@@ -649,7 +651,7 @@ void DialogOptions::Redraw() {
 		if (areawid < data_to_game_coord(_GP(play).min_dialogoption_width)) {
 			areawid = data_to_game_coord(_GP(play).min_dialogoption_width);
 			if (_GP(play).min_dialogoption_width > _GP(play).max_dialogoption_width)
-				quit("!game.min_dialogoption_width is larger than game.max_dialogoption_width");
+				quit("!_GP(game).min_dialogoption_width is larger than _GP(game).max_dialogoption_width");
 		}
 
 		GET_OPTIONS_HEIGHT
@@ -791,6 +793,9 @@ void DialogOptions::Redraw() {
 }
 
 bool DialogOptions::Run() {
+	// Run() can be called in a loop, so keep events going.
+	sys_evt_process_pending();
+
 	const bool new_custom_render = usingCustomRendering && _GP(game).options[OPT_DIALOGOPTIONSAPI] >= 0;
 
 	if (runGameLoopsInBackground) {
@@ -812,7 +817,7 @@ bool DialogOptions::Run() {
 		if (parserInput) {
 			wantRefresh = true;
 			// type into the parser
-			if ((gkey == 361) || ((gkey == ' ') && (strlen(parserInput->Text) == 0))) {
+			if ((gkey == eAGSKeyCodeF3) || ((gkey == eAGSKeyCodeSpace) && (strlen(parserInput->Text) == 0))) {
 				// write previous contents into textbox (F3 or Space when box is empty)
 				for (unsigned int i = strlen(parserInput->Text); i < strlen(_GP(play).lastParserEntry); i++) {
 					parserInput->OnKeyPress(_GP(play).lastParserEntry[i]);
@@ -820,7 +825,7 @@ bool DialogOptions::Run() {
 				//ags_domouse(DOMOUSE_DISABLE);
 				Redraw();
 				return true; // continue running loop
-			} else if ((gkey >= 32) || (gkey == 13) || (gkey == 8)) {
+			} else if ((gkey >= eAGSKeyCodeSpace) || (gkey == eAGSKeyCodeReturn) || (gkey == eAGSKeyCodeBackspace)) {
 				parserInput->OnKeyPress(gkey);
 				if (!parserInput->IsActivated) {
 					//ags_domouse(DOMOUSE_DISABLE);
@@ -830,7 +835,7 @@ bool DialogOptions::Run() {
 			}
 		} else if (new_custom_render) {
 			_GP(runDialogOptionKeyPressHandlerFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
-			_GP(runDialogOptionKeyPressHandlerFunc).params[1].SetInt32(GetKeyForKeyPressCb(gkey));
+			_GP(runDialogOptionKeyPressHandlerFunc).params[1].SetInt32(AGSKeyToScriptKey(gkey));
 			run_function_on_non_blocking_thread(&_GP(runDialogOptionKeyPressHandlerFunc));
 		}
 		// Allow selection of options by keyboard shortcuts
@@ -885,7 +890,7 @@ bool DialogOptions::Run() {
 			parserActivated = 1;
 	}
 
-	int mouseButtonPressed = NONE;
+	int mouseButtonPressed = MouseNone;
 	int mouseWheelTurn = 0;
 	if (run_service_mb_controls(mouseButtonPressed, mouseWheelTurn) && mouseButtonPressed >= 0 &&
 	        !_GP(play).IsIgnoringInput()) {
@@ -934,7 +939,7 @@ bool DialogOptions::Run() {
 
 	if (parserActivated) {
 		// They have selected a custom parser-based option
-		if (!parserInput->Text.IsEmpty()) {
+		if (!parserInput->Text.IsEmpty() != 0) {
 			chose = DLG_OPTION_PARSER;
 			return false; // end dialog options running loop
 		} else {
@@ -961,7 +966,7 @@ bool DialogOptions::Run() {
 
 	update_polled_stuff_if_runtime();
 
-	if (!runGameLoopsInBackground && _GP(play).fast_forward == 0) {
+	if (!runGameLoopsInBackground && (_GP(play).fast_forward == 0)) {
 		// note if runGameLoopsInBackground then it's called inside UpdateGameOnce
 		WaitForNextFrame();
 	}
@@ -1004,9 +1009,10 @@ int show_dialog_options(int _dlgnum, int sayChosenOption, bool _runGameLoopsInBa
 	DlgOpt.Close();
 
 	int dialog_choice = DlgOpt.chose;
-	if (dialog_choice != CHOSE_TEXTPARSER) {
+	if (dialog_choice >= 0) { // NOTE: this condition also excludes CHOSE_TEXTPARSER
+		assert(dialog_choice >= 0 && dialog_choice < MAXTOPICOPTIONS);
 		DialogTopic *dialog_topic = DlgOpt.dtop;
-		int32_t &option_flags = dialog_topic->optionflags[dialog_choice];
+		int &option_flags = dialog_topic->optionflags[dialog_choice];
 		const char *option_name = DlgOpt.dtop->optionnames[dialog_choice];
 
 		option_flags |= DFLG_HASBEENCHOSEN;
@@ -1081,8 +1087,6 @@ void do_conversation(int dlgnum) {
 		}
 
 		int chose = show_dialog_options(dlgnum, SAYCHOSEN_USEFLAG, (_GP(game).options[OPT_RUNGAMEDLGOPTS] != 0));
-		if (SHOULD_QUIT)
-			return;
 
 		if (chose == CHOSE_TEXTPARSER) {
 			_G(said_speech_line) = 0;
@@ -1096,8 +1100,10 @@ void do_conversation(int dlgnum) {
 				EnableInterface();
 				set_mouse_cursor(CURS_ARROW);
 			}
-		} else {
+		} else if (chose >= 0) {
 			tocar = run_dialog_script(dtop, dlgnum, dtop->entrypoints[chose], chose + 1);
+		} else {
+			tocar = RUN_DIALOG_STOP_DIALOG;
 		}
 
 		if (tocar == RUN_DIALOG_GOTO_PREVIOUS) {
@@ -1117,22 +1123,17 @@ void do_conversation(int dlgnum) {
 			}
 			dlgnum = tocar;
 		}
-
 	}
-
 }
 
 // end dialog manager
 
-
 //=============================================================================
 //
 // Script API Functions
 //
 //=============================================================================
 
-
-
 // int (ScriptDialog *sd)
 RuntimeScriptValue Sc_Dialog_GetID(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_INT(ScriptDialog, Dialog_GetID);
diff --git a/engines/ags/engine/ac/dialog.h b/engines/ags/engine/ac/dialog.h
index 025abe9c2a..881c8cbb96 100644
--- a/engines/ags/engine/ac/dialog.h
+++ b/engines/ags/engine/ac/dialog.h
@@ -24,7 +24,7 @@
 #define AGS_ENGINE_AC_DIALOG_H
 
 #include "ags/lib/std/vector.h"
-#include "ags/engine/ac/dynobj/scriptdialog.h"
+#include "ags/engine/ac/dynobj/script_dialog.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dialogoptionsrendering.cpp b/engines/ags/engine/ac/dialog_options_rendering.cpp
similarity index 98%
rename from engines/ags/engine/ac/dialogoptionsrendering.cpp
rename to engines/ags/engine/ac/dialog_options_rendering.cpp
index c36756e712..d49e5e7d28 100644
--- a/engines/ags/engine/ac/dialogoptionsrendering.cpp
+++ b/engines/ags/engine/ac/dialog_options_rendering.cpp
@@ -21,13 +21,15 @@
  */
 
 #include "ags/engine/ac/dialog.h"
-#include "ags/shared/ac/dialogtopic.h"
-#include "ags/engine/ac/dialogoptionsrendering.h"
-#include "ags/shared/ac/gamestructdefines.h"
+#include "ags/shared/ac/dialog_topic.h"
+#include "ags/engine/ac/dialog_options_rendering.h"
+#include "ags/shared/ac/game_struct_defines.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/engine/script/runtimescriptvalue.h"
-#include "ags/engine/script/script_runtime.h"
+#include "ags/engine/script/runtime_script_value.h"
 #include "ags/engine/ac/dynobj/cc_dialog.h"
+#include "ags/shared/debugging/out.h"
+#include "ags/engine/script/script_api.h"
+#include "ags/engine/script/script_runtime.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -137,10 +139,6 @@ void DialogOptionsRendering_SetActiveOptionID(ScriptDialogOptionsRendering *dlgO
 //
 //=============================================================================
 
-#include "ags/shared/debugging/out.h"
-#include "ags/engine/script/script_api.h"
-#include "ags/engine/script/script_runtime.h"
-
 RuntimeScriptValue Sc_DialogOptionsRendering_Update(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_VOID(ScriptDialogOptionsRendering, DialogOptionsRendering_Update);
 }
diff --git a/engines/ags/engine/ac/dialogoptionsrendering.h b/engines/ags/engine/ac/dialog_options_rendering.h
similarity index 93%
rename from engines/ags/engine/ac/dialogoptionsrendering.h
rename to engines/ags/engine/ac/dialog_options_rendering.h
index 2ab24033e2..26c968e195 100644
--- a/engines/ags/engine/ac/dialogoptionsrendering.h
+++ b/engines/ags/engine/ac/dialog_options_rendering.h
@@ -20,11 +20,11 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DIALOGOPTIONSRENDERING_H
-#define AGS_ENGINE_AC_DIALOGOPTIONSRENDERING_H
+#ifndef AGS_ENGINE_AC_DIALOG_OPTIONS_RENDERING_H
+#define AGS_ENGINE_AC_DIALOG_OPTIONS_RENDERING_H
 
-#include "ags/engine/ac/dynobj/scriptdialog.h"
-#include "ags/engine/ac/dynobj/scriptdialogoptionsrendering.h"
+#include "ags/engine/ac/dynobj/script_dialog.h"
+#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index a1ff2d1e1d..045ab4047c 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -20,45 +20,49 @@
  *
  */
 
+#include "ags/lib/std/math.h"
 #include "ags/engine/ac/display.h"
 #include "ags/shared/ac/common.h"
-#include "ags/shared/font/agsfontrenderer.h"
+#include "ags/shared/font/ags_font_renderer.h"
 #include "ags/shared/font/fonts.h"
 #include "ags/engine/ac/character.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/game.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_audio.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/gui.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/sys_events.h"
-#include "ags/engine/ac/screenoverlay.h"
+#include "ags/engine/ac/screen_overlay.h"
 #include "ags/engine/ac/speech.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/ac/system.h"
-#include "ags/engine/ac/topbarsettings.h"
+#include "ags/engine/ac/top_bar_settings.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/engine/gfx/blender.h"
-#include "ags/shared/gui/guibutton.h"
-#include "ags/shared/gui/guimain.h"
+#include "ags/shared/gui/gui_button.h"
+#include "ags/shared/gui/gui_main.h"
 #include "ags/engine/main/game_run.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/gfx/gfx_util.h"
 #include "ags/shared/util/string_utils.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/engine/ac/timer.h"
 #include "ags/globals.h"
-#include "ags/ags.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
-using namespace AGS::Shared::BitmapHelper;
+
+struct DisplayVars {
+	int lineheight;    // font's height of single line
+	int linespacing;   // font's line spacing
+	int fulltxtheight; // total height of all the text
+} disp;
 
 // Pass yy = -1 to find Y co-ord automatically
 // allowShrink = 0 for none, 1 for leftwards, 2 for rightwards
@@ -81,10 +85,10 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 	int paddingDoubledScaled = get_fixed_pixel_size(padding * 2); // Just in case screen size does is not neatly divisible by 320x200
 
 	ensure_text_valid_for_font(todis, usingfont);
-	break_up_text_into_lines(todis, _GP(fontLines), wii - 2 * padding, usingfont);
-	_G(disp).lineheight = getfontheight_outlined(usingfont);
-	_G(disp).linespacing = getfontspacing_outlined(usingfont);
-	_G(disp).fulltxtheight = getheightoflines(usingfont, _GP(fontLines).Count());
+	break_up_text_into_lines(todis, Lines, wii - 2 * padding, usingfont);
+	disp.lineheight = getfontheight_outlined(usingfont);
+	disp.linespacing = getfontspacing_outlined(usingfont);
+	disp.fulltxtheight = getheightoflines(usingfont, Lines.Count());
 
 	// AGS 2.x: If the screen is faded out, fade in again when displaying a message box.
 	if (!asspch && (_G(loaded_game_file_version) <= kGameVersion_272))
@@ -121,10 +125,10 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 	const Rect &ui_view = _GP(play).GetUIViewport();
 	if (xx == OVR_AUTOPLACE);
 	// centre text in middle of screen
-	else if (yy < 0) yy = ui_view.GetHeight() / 2 - _G(disp).fulltxtheight / 2 - padding;
+	else if (yy < 0) yy = ui_view.GetHeight() / 2 - disp.fulltxtheight / 2 - padding;
 	// speech, so it wants to be above the character's head
 	else if (asspch > 0) {
-		yy -= _G(disp).fulltxtheight;
+		yy -= disp.fulltxtheight;
 		if (yy < 5) yy = 5;
 		yy = adjust_y_for_guis(yy);
 	}
@@ -158,7 +162,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 	if (disp_type < DISPLAYTEXT_NORMALOVERLAY)
 		remove_screen_overlay(OVER_TEXTMSG); // remove any previous blocking texts
 
-	Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap((wii > 0) ? wii : 2, _G(disp).fulltxtheight + extraHeight, _GP(game).GetColorDepth());
+	Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap((wii > 0) ? wii : 2, disp.fulltxtheight + extraHeight, _GP(game).GetColorDepth());
 
 	// inform draw_text_window to free the old bitmap
 	const bool wantFreeScreenop = true;
@@ -193,22 +197,23 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 		} else if ((ShouldAntiAliasText()) && (_GP(game).GetColorDepth() >= 24))
 			alphaChannel = true;
 
-		for (size_t ee = 0; ee < _GP(fontLines).Count(); ee++) {
+		for (size_t ee = 0; ee < Lines.Count(); ee++) {
 			//int ttxp=wii/2 - wgettextwidth_compensate(lines[ee], usingfont)/2;
-			int ttyp = ttxtop + ee * _G(disp).linespacing;
+			int ttyp = ttxtop + ee * disp.linespacing;
 			// asspch < 0 means that it's inside a text box so don't
 			// centre the text
 			if (asspch < 0) {
 				if ((usingGui >= 0) &&
-					((_GP(game).options[OPT_SPEECHTYPE] >= 2) || (isThought)))
+				        ((_GP(game).options[OPT_SPEECHTYPE] >= 2) || (isThought)))
 					text_color = text_window_ds->GetCompatibleColor(_GP(guis)[usingGui].FgColor);
 				else
 					text_color = text_window_ds->GetCompatibleColor(-asspch);
 
-				wouttext_aligned(text_window_ds, ttxleft, ttyp, oriwid, usingfont, text_color, _GP(fontLines)[ee], _GP(play).text_align);
+				wouttext_aligned(text_window_ds, ttxleft, ttyp, oriwid, usingfont, text_color, Lines[ee], _GP(play).text_align);
 			} else {
 				text_color = text_window_ds->GetCompatibleColor(asspch);
-				wouttext_aligned(text_window_ds, ttxleft, ttyp, wii, usingfont, text_color, _GP(fontLines)[ee], _GP(play).speech_text_align);
+				//wouttext_outline(ttxp,ttyp,usingfont,lines[ee]);
+				wouttext_aligned(text_window_ds, ttxleft, ttyp, wii, usingfont, text_color, Lines[ee], _GP(play).speech_text_align);
 			}
 		}
 	} else {
@@ -221,8 +226,8 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 
 		adjust_y_coordinate_for_text(&yoffs, usingfont);
 
-		for (size_t ee = 0; ee < _GP(fontLines).Count(); ee++)
-			wouttext_aligned(text_window_ds, xoffs, yoffs + ee * _G(disp).linespacing, oriwid, usingfont, text_color, _GP(fontLines)[ee], _GP(play).text_align);
+		for (size_t ee = 0; ee < Lines.Count(); ee++)
+			wouttext_aligned(text_window_ds, xoffs, yoffs + ee * disp.linespacing, oriwid, usingfont, text_color, Lines[ee], _GP(play).text_align);
 	}
 
 	int ovrtype = OVER_TEXTMSG;
@@ -252,9 +257,8 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 		int countdown = GetTextDisplayTime(todis);
 		int skip_setting = user_to_internal_skip_speech((SkipSpeechStyle)_GP(play).skip_display);
 		// Loop until skipped
-		for (;;) {
-			if (SHOULD_QUIT)
-				return 0;
+		while (true) {
+			sys_evt_process_pending();
 
 			update_audio_system_on_game_loop();
 			render_graphics();
@@ -289,7 +293,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 				if (channel_is_playing(SCHAN_SPEECH) && (_GP(play).fast_forward == 0)) {
 					if (countdown <= 1)
 						countdown = 1;
-				} else // if the voice has finished, remove the speech
+				} else  // if the voice has finished, remove the speech
 					countdown = 0;
 			}
 			// Test for the timed auto-skip
@@ -335,8 +339,7 @@ void _display_at(int xx, int yy, int wii, const char *text, int disp_type, int a
 
 	EndSkippingUntilCharStops();
 
-	if (try_auto_play_speech(text, text, _GP(play).narrator_speech, true)) {
-		// TODO: is there any need for this flag?
+	if (try_auto_play_speech(text, text, _GP(play).narrator_speech, true)) {// TODO: is there any need for this flag?
 		need_stop_speech = true;
 	}
 	_display_main(xx, yy, wii, text, disp_type, usingfont, asspch, isThought, allowShrink, overlayPositionFixed);
@@ -400,7 +403,7 @@ int GetTextDisplayTime(const char *text, int canberel) {
 		return 0;
 
 	if (_GP(play).text_speed + _GP(play).text_speed_modifier <= 0)
-		quit("!Text speed is zero; unable to display text. Check your game.text_speed settings.");
+		quit("!Text speed is zero; unable to display text. Check your _GP(game).text_speed settings.");
 
 	// Store how many game loops per character of text
 	// This is calculated using a hard-coded 15 for the text speed,
@@ -416,21 +419,19 @@ int GetTextDisplayTime(const char *text, int canberel) {
 }
 
 bool ShouldAntiAliasText() {
-	return (_GP(game).options[OPT_ANTIALIASFONTS] != 0 || ::AGS::g_vm->_forceTextAA);
+	return (_GP(game).options[OPT_ANTIALIASFONTS] != 0);
 }
 
-// Draw an outline if requested, then draw the text on top
-void wouttext_outline(Shared::Bitmap *ds, int xxp, int yyp, int font, color_t text_color, const char *texx) {
-	size_t const text_font = static_cast<size_t>(font);
-	// Draw outline (a backdrop) if requested
-	color_t const outline_color = ds->GetCompatibleColor(_GP(play).speech_text_shadow);
-	int const outline_font = get_font_outline(font);
-	if (outline_font >= 0)
-		wouttextxy(ds, xxp, yyp, static_cast<size_t>(outline_font), outline_color, texx);
-	else if (outline_font == FONT_OUTLINE_AUTO) {
+void wouttext_outline(Shared::Bitmap *ds, int xxp, int yyp, int usingfont, color_t text_color, const char *texx) {
+
+	color_t outline_color = ds->GetCompatibleColor(_GP(play).speech_text_shadow);
+	if (get_font_outline(usingfont) >= 0) {
+		// MACPORT FIX 9/6/5: cast
+		wouttextxy(ds, xxp, yyp, (int)get_font_outline(usingfont), outline_color, texx);
+	} else if (get_font_outline(usingfont) == FONT_OUTLINE_AUTO) {
 		int outlineDist = 1;
 
-		if (is_bitmap_font(font) && get_font_scaling_mul(font) > 1) {
+		if (is_bitmap_font(usingfont) && get_font_scaling_mul(usingfont) > 1) {
 			// if it's a scaled up bitmap font, move the outline out more
 			outlineDist = get_fixed_pixel_size(1);
 		}
@@ -439,18 +440,17 @@ void wouttext_outline(Shared::Bitmap *ds, int xxp, int yyp, int font, color_t te
 		xxp += outlineDist;
 		yyp += outlineDist;
 
-		wouttextxy(ds, xxp - outlineDist, yyp, text_font, outline_color, texx);
-		wouttextxy(ds, xxp + outlineDist, yyp, text_font, outline_color, texx);
-		wouttextxy(ds, xxp, yyp + outlineDist, text_font, outline_color, texx);
-		wouttextxy(ds, xxp, yyp - outlineDist, text_font, outline_color, texx);
-		wouttextxy(ds, xxp - outlineDist, yyp - outlineDist, text_font, outline_color, texx);
-		wouttextxy(ds, xxp - outlineDist, yyp + outlineDist, text_font, outline_color, texx);
-		wouttextxy(ds, xxp + outlineDist, yyp + outlineDist, text_font, outline_color, texx);
-		wouttextxy(ds, xxp + outlineDist, yyp - outlineDist, text_font, outline_color, texx);
+		wouttextxy(ds, xxp - outlineDist, yyp, usingfont, outline_color, texx);
+		wouttextxy(ds, xxp + outlineDist, yyp, usingfont, outline_color, texx);
+		wouttextxy(ds, xxp, yyp + outlineDist, usingfont, outline_color, texx);
+		wouttextxy(ds, xxp, yyp - outlineDist, usingfont, outline_color, texx);
+		wouttextxy(ds, xxp - outlineDist, yyp - outlineDist, usingfont, outline_color, texx);
+		wouttextxy(ds, xxp - outlineDist, yyp + outlineDist, usingfont, outline_color, texx);
+		wouttextxy(ds, xxp + outlineDist, yyp + outlineDist, usingfont, outline_color, texx);
+		wouttextxy(ds, xxp + outlineDist, yyp - outlineDist, usingfont, outline_color, texx);
 	}
 
-	// Draw text on top
-	wouttextxy(ds, xxp, yyp, text_font, text_color, texx);
+	wouttextxy(ds, xxp, yyp, usingfont, text_color, texx);
 }
 
 void wouttext_aligned(Bitmap *ds, int usexp, int yy, int oriwid, int usingfont, color_t text_color, const char *text, HorAlignment align) {
@@ -460,7 +460,7 @@ void wouttext_aligned(Bitmap *ds, int usexp, int yy, int oriwid, int usingfont,
 	else if (align & kMAlignRight)
 		usexp = usexp + (oriwid - wgettextwidth_compensate(text, usingfont));
 
-	wouttext_outline(ds, usexp, yy, usingfont, text_color, (const char *)text);
+	wouttext_outline(ds, usexp, yy, usingfont, text_color, text);
 }
 
 int get_outline_adjustment(int font) {
@@ -482,8 +482,8 @@ int getfontheight_outlined(int font) {
 
 int getfontspacing_outlined(int font) {
 	return use_default_linespacing(font) ?
-		getfontheight_outlined(font) :
-		getfontlinespacing(font);
+	       getfontheight_outlined(font) :
+	       getfontlinespacing(font);
 }
 
 int getfontlinegap(int font) {
@@ -527,7 +527,7 @@ int get_but_pic(GUIMain *guo, int indx) {
 
 void draw_button_background(Bitmap *ds, int xx1, int yy1, int xx2, int yy2, GUIMain *iep) {
 	color_t draw_color;
-	if (iep == nullptr) { // standard window
+	if (iep == nullptr) {  // standard window
 		draw_color = ds->GetCompatibleColor(15);
 		ds->FillRect(Rect(xx1, yy1, xx2, yy2), draw_color);
 		draw_color = ds->GetCompatibleColor(16);
@@ -554,9 +554,9 @@ void draw_button_background(Bitmap *ds, int xx1, int yy1, int xx2, int yy2, GUIM
 		int topBottomHeight = _GP(game).SpriteInfos[get_but_pic(iep, 6)].Height;
 		if (iep->BgImage > 0) {
 			if ((_G(loaded_game_file_version) <= kGameVersion_272) // 2.xx
-				&& (_GP(spriteset)[iep->BgImage]->GetWidth() == 1)
-				&& (_GP(spriteset)[iep->BgImage]->GetHeight() == 1)
-				&& (*((const unsigned int *)_GP(spriteset)[iep->BgImage]->GetData()) == 0x00FF00FF)) {
+			        && (_GP(spriteset)[iep->BgImage]->GetWidth() == 1)
+			        && (_GP(spriteset)[iep->BgImage]->GetHeight() == 1)
+			        && (*((const unsigned int *)_GP(spriteset)[iep->BgImage]->GetData()) == 0x00FF00FF)) {
 				// Don't draw fully transparent dummy GUI backgrounds
 			} else {
 				// offset the background image and clip it so that it is drawn
@@ -582,17 +582,17 @@ void draw_button_background(Bitmap *ds, int xx1, int yy1, int xx2, int yy2, GUIM
 		}
 		int uu;
 		for (uu = yy1; uu <= yy2; uu += _GP(game).SpriteInfos[get_but_pic(iep, 4)].Height) {
-			do_corner(ds, get_but_pic(iep, 4), xx1, uu, -1, 0); // left side
-			do_corner(ds, get_but_pic(iep, 5), xx2 + 1, uu, 0, 0); // right side
+			do_corner(ds, get_but_pic(iep, 4), xx1, uu, -1, 0);   // left side
+			do_corner(ds, get_but_pic(iep, 5), xx2 + 1, uu, 0, 0);  // right side
 		}
 		for (uu = xx1; uu <= xx2; uu += _GP(game).SpriteInfos[get_but_pic(iep, 6)].Width) {
-			do_corner(ds, get_but_pic(iep, 6), uu, yy1, 0, -1); // top side
+			do_corner(ds, get_but_pic(iep, 6), uu, yy1, 0, -1);  // top side
 			do_corner(ds, get_but_pic(iep, 7), uu, yy2 + 1, 0, 0); // bottom side
 		}
-		do_corner(ds, get_but_pic(iep, 0), xx1, yy1, -1, -1); // top left
-		do_corner(ds, get_but_pic(iep, 1), xx1, yy2 + 1, -1, 0); // bottom left
-		do_corner(ds, get_but_pic(iep, 2), xx2 + 1, yy1, 0, -1); //  top right
-		do_corner(ds, get_but_pic(iep, 3), xx2 + 1, yy2 + 1, 0, 0); // bottom right
+		do_corner(ds, get_but_pic(iep, 0), xx1, yy1, -1, -1);  // top left
+		do_corner(ds, get_but_pic(iep, 1), xx1, yy2 + 1, -1, 0);  // bottom left
+		do_corner(ds, get_but_pic(iep, 2), xx2 + 1, yy1, 0, -1);  //  top right
+		do_corner(ds, get_but_pic(iep, 3), xx2 + 1, yy2 + 1, 0, 0);  // bottom right
 	}
 }
 
@@ -606,7 +606,7 @@ int get_textwindow_border_width(int twgui) {
 		quit("!GUI set as text window but is not actually a text window GUI");
 
 	int borwid = _GP(game).SpriteInfos[get_but_pic(&_GP(guis)[twgui], 4)].Width +
-		_GP(game).SpriteInfos[get_but_pic(&_GP(guis)[twgui], 5)].Width;
+	             _GP(game).SpriteInfos[get_but_pic(&_GP(guis)[twgui], 5)].Width;
 
 	return borwid;
 }
@@ -638,7 +638,7 @@ int get_textwindow_padding(int ifnum) {
 }
 
 void draw_text_window(Bitmap **text_window_ds, bool should_free_ds,
-	int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum) {
+                      int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum) {
 
 	Bitmap *ds = *text_window_ds;
 	if (ifnum < 0)
@@ -664,7 +664,7 @@ void draw_text_window(Bitmap **text_window_ds, bool should_free_ds,
 		xx[0] -= _GP(game).SpriteInfos[tbnum].Width;
 		yy[0] -= _GP(game).SpriteInfos[tbnum].Height;
 		if (ovrheight == 0)
-			ovrheight = _G(disp).fulltxtheight;
+			ovrheight = disp.fulltxtheight;
 
 		if (should_free_ds)
 			delete *text_window_ds;
@@ -681,7 +681,7 @@ void draw_text_window(Bitmap **text_window_ds, bool should_free_ds,
 }
 
 void draw_text_window_and_bar(Bitmap **text_window_ds, bool should_free_ds,
-	int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum) {
+                              int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum) {
 
 	draw_text_window(text_window_ds, should_free_ds, xins, yins, xx, yy, wii, set_text_color, ovrheight, ifnum);
 
diff --git a/engines/ags/engine/ac/display.h b/engines/ags/engine/ac/display.h
index d3ea28f6eb..5928dff6f9 100644
--- a/engines/ags/engine/ac/display.h
+++ b/engines/ags/engine/ac/display.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DISPLAY_H
 #define AGS_ENGINE_AC_DISPLAY_H
 
-#include "ags/shared/gui/guimain.h"
+#include "ags/shared/gui/gui_main.h"
 
 namespace AGS3 {
 
@@ -47,12 +47,11 @@ bool ShouldAntiAliasText();
 int GetTextDisplayLength(const char *text);
 // Calculates number of game loops for displaying a text on screen
 int GetTextDisplayTime(const char *text, int canberel = 0);
-// Draw an outline if requested, then draw the text on top
 void wouttext_outline(Shared::Bitmap *ds, int xxp, int yyp, int usingfont, color_t text_color, const char *texx);
 void wouttext_aligned(Shared::Bitmap *ds, int usexp, int yy, int oriwid, int usingfont, color_t text_color, const char *text, HorAlignment align);
 // TODO: GUI classes located in Common library do not make use of outlining,
 // need to find a way to make all code use same functions.
-// Get the maximal height of the given font, with corresponding outlining
+// Get the maximal height of the given font, with possible outlining in mind
 int getfontheight_outlined(int font);
 // Get line spacing for the given font, with possible outlining in mind
 int getfontspacing_outlined(int font);
@@ -60,7 +59,6 @@ int getfontspacing_outlined(int font);
 int getfontlinegap(int font);
 // Gets the total maximal height of the given number of lines printed with the given font
 int getheightoflines(int font, int numlines);
-// Get the maximal width of the given font, with corresponding outlining
 int wgettextwidth_compensate(const char *tex, int font);
 void do_corner(Shared::Bitmap *ds, int sprn, int xx1, int yy1, int typx, int typy);
 // Returns the image of a button control on the GUI under given child index
@@ -78,7 +76,7 @@ int get_textwindow_top_border_height(int twgui);
 // Warning!: draw_text_window() and draw_text_window_and_bar() can create new text_window_ds
 void draw_text_window(Shared::Bitmap **text_window_ds, bool should_free_ds, int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight, int ifnum);
 void draw_text_window_and_bar(Shared::Bitmap **text_window_ds, bool should_free_ds,
-	int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight = 0, int ifnum = -1);
+                              int *xins, int *yins, int *xx, int *yy, int *wii, color_t *set_text_color, int ovrheight = 0, int ifnum = -1);
 int get_textwindow_padding(int ifnum);
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 057479f81c..2e49f6c053 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -26,47 +26,47 @@
 #include "ags/shared/core/platform.h"
 #include "ags/shared/ac/common.h"
 #include "ags/shared/util/compress.h"
+#include "ags/shared/util/wgt2_allg.h"
 #include "ags/shared/ac/view.h"
-#include "ags/engine/ac/charactercache.h"
-#include "ags/engine/ac/characterextras.h"
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/engine/ac/character_cache.h"
+#include "ags/engine/ac/character_extras.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/draw_software.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/global_gui.h"
 #include "ags/engine/ac/global_region.h"
 #include "ags/engine/ac/gui.h"
 #include "ags/engine/ac/mouse.h"
-#include "ags/engine/ac/objectcache.h"
+#include "ags/engine/ac/object_cache.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/sys_events.h"
-#include "ags/engine/ac/roomobject.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_object.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/ac/runtime_defines.h"
-#include "ags/engine/ac/screenoverlay.h"
+#include "ags/engine/ac/screen_overlay.h"
 #include "ags/engine/ac/sprite.h"
-#include "ags/engine/ac/spritelistentry.h"
+#include "ags/engine/ac/sprite_list_entry.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/ac/system.h"
-#include "ags/engine/ac/viewframe.h"
-#include "ags/engine/ac/walkablearea.h"
-#include "ags/engine/ac/walkbehind.h"
-#include "ags/engine/ac/dynobj/scriptsystem.h"
+#include "ags/engine/ac/view_frame.h"
+#include "ags/engine/ac/walkable_area.h"
+#include "ags/engine/ac/walk_behind.h"
+#include "ags/engine/ac/dynobj/script_system.h"
 #include "ags/engine/debugging/debugger.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/shared/font/fonts.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
-#include "ags/plugins/agsplugin.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
+#include "ags/plugins/ags_plugin.h"
 #include "ags/plugins/plugin_engine.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/gfx/gfx_util.h"
-#include "ags/engine/gfx/graphicsdriver.h"
-#include "ags/engine/gfx/ali3dexception.h"
+#include "ags/engine/gfx/graphics_driver.h"
 #include "ags/engine/gfx/blender.h"
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/engine/ac/game.h"
@@ -77,17 +77,6 @@ namespace AGS3 {
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
-#if AGS_PLATFORM_OS_ANDROID
-//include <sys/stat.h>
-//include <android/log.h>
-
-extern "C" void android_render();
-#endif
-
-#if AGS_PLATFORM_OS_IOS
-extern "C" void ios_render();
-#endif
-
 SpriteListEntry::SpriteListEntry()
 	: bmp(nullptr)
 	, pic(nullptr)
@@ -100,6 +89,8 @@ void setpal() {
 	set_palette_range(_G(palette), 0, 255, 0);
 }
 
+int _places_r = 3, _places_g = 2, _places_b = 3;
+
 // convert RGB to BGR for strange graphics cards
 Bitmap *convert_16_to_16bgr(Bitmap *tempbl) {
 
@@ -116,9 +107,9 @@ Bitmap *convert_16_to_16bgr(Bitmap *tempbl) {
 				ds = _rgb_scale_6[(c >> 5) & 0x3F];
 				r = _rgb_scale_5[(c >> 11) & 0x1F];
 				// allegro assumes 5-6-5 for 16-bit
-				p16[x] = (((r >> _G(places_r)) << _G(_rgb_r_shift_16)) |
-				          ((ds >> _G(places_g)) << _G(_rgb_g_shift_16)) |
-				          ((b >> _G(places_b)) << _G(_rgb_b_shift_16)));
+				p16[x] = (((r >> _places_r) << _G(_rgb_r_shift_16)) |
+				          ((ds >> _places_g) << _G(_rgb_g_shift_16)) |
+				          ((b >> _places_b) << _G(_rgb_b_shift_16)));
 
 			}
 		}
@@ -164,7 +155,7 @@ Bitmap *convert_32_to_32bgr(Bitmap *tempbl) {
 //
 Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
 	const int bmp_col_depth = bitmap->GetColorDepth();
-	//const int sys_col_depth = System_GetColorDepth();
+	// const int sys_col_depth = System_GetColorDepth();
 	const int game_col_depth = _GP(game).GetColorDepth();
 	Bitmap *new_bitmap = bitmap;
 
@@ -356,15 +347,18 @@ AGS_INLINE void defgame_to_finalgame_coords(int &x, int &y) {
 void create_blank_image(int coldepth) {
 	// this is the first time that we try to use the graphics driver,
 	// so it's the most likey place for a crash
-//	try {
-		Bitmap *blank = BitmapHelper::CreateBitmap(16, 16, coldepth);
-		blank = ReplaceBitmapWithSupportedFormat(blank);
-		blank->Clear();
-		_G(blankImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
-		_G(blankSidebarImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
-		delete blank;
-/*	} catch (Ali3DException gfxException) {
-		quit((char *)gfxException._message);
+	//try
+	//{
+	Bitmap *blank = BitmapHelper::CreateBitmap(16, 16, coldepth);
+	blank = ReplaceBitmapWithSupportedFormat(blank);
+	blank->Clear();
+	_G(blankImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
+	_G(blankSidebarImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
+	delete blank;
+	/*}
+	catch (Ali3DException gfxException)
+	{
+	    quit((char*)gfxException._message);
 	}*/
 }
 
@@ -509,7 +503,7 @@ void detect_roomviewport_overlaps(size_t z_index) {
 		const int this_id = this_view->GetID();
 		bool is_overlap = false;
 		if (!this_view->IsVisible()) continue;
-		for (size_t z_index2 = 0; z_index2 < z_index; ++z_index) {
+		for (size_t z_index2 = 0; z_index2 < z_index; ++z_index2) {
 			if (!viewports[z_index2]->IsVisible()) continue;
 			if (AreRectsIntersecting(this_view->GetRect(), viewports[z_index2]->GetRect())) {
 				is_overlap = true;
@@ -570,7 +564,7 @@ void mark_current_background_dirty() {
 
 
 void draw_and_invalidate_text(Bitmap *ds, int x1, int y1, int font, color_t text_color, const char *text) {
-	wouttext_outline(ds, x1, y1, font, text_color, (const char *)text);
+	wouttext_outline(ds, x1, y1, font, text_color, text);
 	invalidate_rect(x1, y1, x1 + wgettextwidth_compensate(text, font), y1 + getfontheight_outlined(font) + get_fixed_pixel_size(1), false);
 }
 
@@ -612,24 +606,27 @@ void render_to_screen() {
 
 	bool succeeded = false;
 	while (!succeeded) {
-//		try {
-			// For software renderer, need to blacken upper part of the game frame when shaking screen moves image down
-			const Rect &viewport = _GP(play).GetMainViewport();
-			if (_GP(play).shake_screen_yoff > 0 && !_G(gfxDriver)->RequiresFullRedrawEachFrame())
-				_G(gfxDriver)->ClearRectangle(viewport.Left, viewport.Top, viewport.GetWidth() - 1, _GP(play).shake_screen_yoff, nullptr);
-			_G(gfxDriver)->Render(0, _GP(play).shake_screen_yoff, (GlobalFlipType)_GP(play).screen_flipped);
+		//     try
+		//     {
+		// For software renderer, need to blacken upper part of the game frame when shaking screen moves image down
+		const Rect &viewport = _GP(play).GetMainViewport();
+		if (_GP(play).shake_screen_yoff > 0 && !_G(gfxDriver)->RequiresFullRedrawEachFrame())
+			_G(gfxDriver)->ClearRectangle(viewport.Left, viewport.Top, viewport.GetWidth() - 1, _GP(play).shake_screen_yoff, nullptr);
+		_G(gfxDriver)->Render(0, _GP(play).shake_screen_yoff, (GlobalFlipType)_GP(play).screen_flipped);
 
 #if AGS_PLATFORM_OS_ANDROID
-			if (_GP(game).color_depth == 1)
-				android_render();
+		if (_GP(game).color_depth == 1)
+			android_render();
 #elif AGS_PLATFORM_OS_IOS
-			if (_GP(game).color_depth == 1)
-				ios_render();
+		if (_GP(game).color_depth == 1)
+			ios_render();
 #endif
 
-			succeeded = true;
-/*		} catch (Ali3DFullscreenLostException) {
-			_G(platform)->Delay(500);
+		succeeded = true;
+		/*}
+		catch (Ali3DFullscreenLostException)
+		{
+		    platform->Delay(500);
 		}*/
 	}
 }
@@ -661,7 +658,7 @@ void putpixel_compensate(Bitmap *ds, int xx, int yy, int col) {
 
 
 void draw_sprite_support_alpha(Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Bitmap *image, bool src_has_alpha,
-							   BlendMode blend_mode, int alpha) {
+                               BlendMode blend_mode, int alpha) {
 	if (alpha <= 0)
 		return;
 
@@ -678,7 +675,7 @@ void draw_sprite_support_alpha(Bitmap *ds, bool ds_has_alpha, int xpos, int ypos
 }
 
 void draw_sprite_slot_support_alpha(Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, int src_slot,
-									BlendMode blend_mode, int alpha) {
+                                    BlendMode blend_mode, int alpha) {
 	draw_sprite_support_alpha(ds, ds_has_alpha, xpos, ypos, _GP(spriteset)[src_slot], (_GP(game).SpriteInfos[src_slot].Flags & SPF_ALPHACHANNEL) != 0,
 	                          blend_mode, alpha);
 }
@@ -988,9 +985,9 @@ Bitmap *recycle_bitmap(Bitmap *bimp, int coldep, int wid, int hit, bool make_tra
 // tint_amnt will be set to 0 if there is no tint enabled
 // if this is the case, then light_lev holds the light level (0=none)
 void get_local_tint(int xpp, int ypp, int nolight,
-					int *tint_amnt, int *tint_r, int *tint_g,
-					int *tint_b, int *tint_lit,
-					int *light_lev) {
+                    int *tint_amnt, int *tint_r, int *tint_g,
+                    int *tint_b, int *tint_lit,
+                    int *light_lev) {
 
 	int tint_level = 0, light_level = 0;
 	int tint_amount = 0;
@@ -1072,9 +1069,9 @@ void get_local_tint(int xpp, int ypp, int nolight,
 // Applies the specified RGB Tint or Light Level to the _G(actsps)
 // sprite indexed with actspsindex
 void apply_tint_or_light(int actspsindex, int light_level,
-						 int tint_amount, int tint_red, int tint_green,
-						 int tint_blue, int tint_light, int coldept,
-						 Bitmap *blitFrom) {
+                         int tint_amount, int tint_red, int tint_green,
+                         int tint_blue, int tint_light, int coldept,
+                         Bitmap *blitFrom) {
 
 // In a 256-colour game, we cannot do tinting or lightening
 // (but we can do darkening, if light_level < 0)
@@ -1140,8 +1137,8 @@ void apply_tint_or_light(int actspsindex, int light_level,
 // Returns 1 if something was drawn to _G(actsps); returns 0 if no
 // scaling or stretching was required, in which case nothing was done
 int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
-						  int sppic, int newwidth, int newheight,
-						  int isMirrored) {
+                          int sppic, int newwidth, int newheight,
+                          int isMirrored) {
 
 	int actsps_used = 1;
 
@@ -1154,7 +1151,7 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 
 		_G(our_eip) = 334;
 
-		// Ensure that anti-aliasing routines have a palette to
+		// Ensure that anti-aliasing routines have a _G(palette) to
 		// use for mapping while faded out
 		if (_G(in_new_room))
 			select_palette(_G(palette));
@@ -1234,20 +1231,22 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 	int zoom_level = 100;
 
 	// calculate the zoom level
-	if ((_G(objs)[aa].flags & OBJF_USEROOMSCALING) == 0) {
-		zoom_level = _G(objs)[aa].zoom;
-	} else {
+	if (_G(objs)[aa].flags & OBJF_USEROOMSCALING) {
 		int onarea = get_walkable_area_at_location(_G(objs)[aa].x, _G(objs)[aa].y);
+
 		if ((onarea <= 0) && (_GP(thisroom).WalkAreas[0].ScalingFar == 0)) {
 			// just off the edge of an area -- use the scaling we had
 			// while on the area
-			zoom_level = _G(objs)[aa].zoom;
+			zoom_level = _G(objs)[aa].last_zoom;
 		} else
 			zoom_level = get_area_scaling(onarea, _G(objs)[aa].x, _G(objs)[aa].y);
+
+		if (zoom_level != 100)
+			scale_sprite_size(_G(objs)[aa].num, zoom_level, &sprwidth, &sprheight);
+
 	}
-	if (zoom_level != 100)
-		scale_sprite_size(_G(objs)[aa].num, zoom_level, &sprwidth, &sprheight);
-	_G(objs)[aa].zoom = zoom_level;
+	// save the zoom level for next time
+	_G(objs)[aa].last_zoom = zoom_level;
 
 	// save width/height into parameters if requested
 	if (drawnWidth)
@@ -1283,7 +1282,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 
 	// check whether the image should be flipped
 	int isMirrored = 0;
-	if ((_G(objs)[aa].view >= 0) &&
+	if ((_G(objs)[aa].view != (uint16_t)-1) &&
 	        (_G(views)[_G(objs)[aa].view].loops[_G(objs)[aa].loop].frames[_G(objs)[aa].frame].pic == _G(objs)[aa].num) &&
 	        ((_G(views)[_G(objs)[aa].view].loops[_G(objs)[aa].loop].frames[_G(objs)[aa].frame].flags & VFLG_FLIPSPRITE) != 0)) {
 		isMirrored = 1;
@@ -1415,7 +1414,7 @@ void prepare_objects_for_drawing() {
 				usebasel += _GP(thisroom).Height;
 			}
 		} else if (_G(walkBehindMethod) == DrawAsSeparateCharSprite) {
-			sort_out_char_sprite_walk_behind(useindx, atxp, atyp, usebasel, _G(objs)[aa].zoom, _G(objs)[aa].last_width, _G(objs)[aa].last_height);
+			sort_out_char_sprite_walk_behind(useindx, atxp, atyp, usebasel, _G(objs)[aa].last_zoom, _G(objs)[aa].last_width, _G(objs)[aa].last_height);
 		} else if ((!actspsIntact) && (_G(walkBehindMethod) == DrawOverCharSprite)) {
 			sort_out_walk_behinds(_G(actsps)[useindx], atxp, atyp, usebasel);
 		}
@@ -1468,9 +1467,9 @@ void tint_image(Bitmap *ds, Bitmap *srcimg, int red, int grn, int blu, int light
 	// when light is being adjusted and when it is not.
 	// If luminance >= 250, then normal brightness, otherwise darken
 	if (luminance >= 250)
-		set_blender_mode(kTintBlenderMode, red, grn, blu, 0);
+		set_blender_mode(_myblender_color15, _myblender_color16, _myblender_color32, red, grn, blu, 0);
 	else
-		set_blender_mode(kTintLightBlenderMode, red, grn, blu, 0);
+		set_blender_mode(_myblender_color15_light, _myblender_color16_light, _myblender_color32_light, red, grn, blu, 0);
 
 	if (light_level >= 100) {
 		// fully colourised
@@ -1537,12 +1536,10 @@ void prepare_characters_for_drawing() {
 		onarea = get_walkable_area_at_character(aa);
 		_G(our_eip) = 332;
 
-		// calculate the zoom level
 		if (chin->flags & CHF_MANUALSCALING)  // character ignores scaling
 			zoom_level = _G(charextra)[aa].zoom;
 		else if ((onarea <= 0) && (_GP(thisroom).WalkAreas[0].ScalingFar == 0)) {
 			zoom_level = _G(charextra)[aa].zoom;
-			// NOTE: room objects don't have this fix
 			if (zoom_level == 0)
 				zoom_level = 100;
 		} else
@@ -1865,18 +1862,20 @@ void draw_fps(const Rect &viewport) {
 
 // Draw GUI and overlays of all kinds, anything outside the room space
 void draw_gui_and_overlays() {
+	int gg;
+
 	if (pl_any_want_hook(AGSE_PREGUIDRAW))
 		add_thing_to_draw(nullptr, AGSE_PREGUIDRAW, 0, TRANS_RUN_PLUGIN, false);
 
 	// draw overlays, except text boxes and portraits
-	for (const auto &over : _GP(screenover)) {
+	for (gg = 0; gg < _G(numscreenover); gg++) {
 		// complete overlay draw in non-transparent mode
-		if (over.type == OVER_COMPLETE)
-			add_thing_to_draw(over.bmp, over.x, over.y, TRANS_OPAQUE, false);
-		else if (over.type != OVER_TEXTMSG && over.type != OVER_PICTURE) {
+		if (_GP(screenover)[gg].type == OVER_COMPLETE)
+			add_thing_to_draw(_GP(screenover)[gg].bmp, _GP(screenover)[gg].x, _GP(screenover)[gg].y, TRANS_OPAQUE, false);
+		else if (_GP(screenover)[gg].type != OVER_TEXTMSG && _GP(screenover)[gg].type != OVER_PICTURE) {
 			int tdxp, tdyp;
-			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, over.hasAlphaChannel);
+			get_overlay_position(_GP(screenover)[gg], &tdxp, &tdyp);
+			add_thing_to_draw(_GP(screenover)[gg].bmp, tdxp, tdyp, 0, _GP(screenover)[gg].hasAlphaChannel);
 		}
 	}
 
@@ -1890,14 +1889,18 @@ void draw_gui_and_overlays() {
 			quit("!The player.activeinv variable has been corrupted, probably as a result\n"
 			     "of an incorrect assignment in the game script.");
 		}
-		if (_G(playerchar)->activeinv < 1) _G(gui_inv_pic) = -1;
-		else _G(gui_inv_pic) = _GP(game).invinfo[_G(playerchar)->activeinv].pic;
+		if (_G(playerchar)->activeinv < 1)
+			_G(gui_inv_pic) = -1;
+		else
+			_G(gui_inv_pic) = _GP(game).invinfo[_G(playerchar)->activeinv].pic;
 		_G(our_eip) = 37;
-		if (_G(guis_need_update)) {
-			_G(guis_need_update) = 0;
+		{
 			for (aa = 0; aa < _GP(game).numgui; aa++) {
 				if (!_GP(guis)[aa].IsDisplayed()) continue;
+				if (!_GP(guis)[aa].HasChanged()) continue;
+				if (_GP(guis)[aa].Transparency == 255) continue;
 
+				_GP(guis)[aa].ClearChanged();
 				if (_G(guibg)[aa] == nullptr)
 					recreate_guibg_image(&_GP(guis)[aa]);
 
@@ -1928,9 +1931,10 @@ void draw_gui_and_overlays() {
 		}
 		_G(our_eip) = 38;
 		// Draw the GUIs
-		for (int gg = 0; gg < _GP(game).numgui; gg++) {
+		for (gg = 0; gg < _GP(game).numgui; gg++) {
 			aa = _GP(play).gui_draw_order[gg];
 			if (!_GP(guis)[aa].IsDisplayed()) continue;
+			if (_GP(guis)[aa].Transparency == 255) continue;
 
 			// Don't draw GUI if "GUIs Turn Off When Disabled"
 			if ((_GP(game).options[OPT_DISABLEOFF] == 3) &&
@@ -1948,11 +1952,11 @@ void draw_gui_and_overlays() {
 	}
 
 	// draw speech and portraits (so that they appear over GUIs)
-	for (const auto &over : _GP(screenover)) {
-		if (over.type == OVER_TEXTMSG || over.type == OVER_PICTURE) {
+	for (gg = 0; gg < _G(numscreenover); gg++) {
+		if (_GP(screenover)[gg].type == OVER_TEXTMSG || _GP(screenover)[gg].type == OVER_PICTURE) {
 			int tdxp, tdyp;
-			get_overlay_position(over, &tdxp, &tdyp);
-			add_thing_to_draw(over.bmp, tdxp, tdyp, 0, false);
+			get_overlay_position(_GP(screenover)[gg], &tdxp, &tdyp);
+			add_thing_to_draw(_GP(screenover)[gg].bmp, tdxp, tdyp, 0, false);
 		}
 	}
 
@@ -2144,7 +2148,8 @@ void construct_game_screen_overlay(bool draw_mouse) {
 
 	// Stage: mouse cursor
 	if (draw_mouse && !_GP(play).mouse_cursor_hidden && _GP(play).screen_is_faded_out == 0) {
-		_G(gfxDriver)->DrawSprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), _G(mouseCursor));
+		_G(gfxDriver)->DrawSprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty),
+		                          _G(mouseCursor));
 		invalidate_sprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), _G(mouseCursor), false);
 	}
 
@@ -2233,7 +2238,7 @@ void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY
 	render_to_screen();
 
 	if (!_GP(play).screen_is_faded_out) {
-		// always update the palette, regardless of whether the plugin
+		// always update the _G(palette), regardless of whether the plugin
 		// vetos the screen update
 		if (_G(bg_just_changed)) {
 			setpal();
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index b9d246f8a0..237272412d 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -27,10 +27,8 @@
 #include "ags/shared/core/types.h"
 #include "ags/shared/ac/common_defines.h"
 #include "ags/shared/gfx/gfx_def.h"
-#include "ags/shared/util/wgt2allg.h"
 
 namespace AGS3 {
-
 namespace AGS {
 namespace Shared {
 class Bitmap;
@@ -46,17 +44,6 @@ using namespace AGS; // FIXME later
 
 #define IS_ANTIALIAS_SPRITES _GP(usetup).enable_antialiasing && (_GP(play).disable_antialiasing == 0)
 
-// [IKM] WARNING: these definitions has to be made AFTER Allegro headers
-// were included, because they override few Allegro function names;
-// otherwise Allegro headers should not be included at all to the same
-// code unit which uses these defines.
-#define getr32(xx) ((xx >> _G(_rgb_r_shift_32)) & 0xFF)
-#define getg32(xx) ((xx >> _G(_rgb_g_shift_32)) & 0xFF)
-#define getb32(xx) ((xx >> _G(_rgb_b_shift_32)) & 0xFF)
-#define geta32(xx) ((xx >> _G(_rgb_a_shift_32)) & 0xFF)
-#define makeacol32(r,g,b,a) ((r << _G(_rgb_r_shift_32)) | (g << _G(_rgb_g_shift_32)) | (b << _G(_rgb_b_shift_32)) | (a << _G(_rgb_a_shift_32)))
-
-
 struct CachedActSpsData {
 	int xWas, yWas;
 	int baselineWas;
@@ -75,11 +62,10 @@ struct RoomCameraDrawData {
 	// For more details see comment in ALSoftwareGraphicsDriver::RenderToBackBuffer().
 	AGS::Shared::PBitmap Buffer;      // this is the actual bitmap
 	AGS::Shared::PBitmap Frame;       // this is either same bitmap reference or sub-bitmap of virtual screen
-	bool    IsOffscreen = false; // whether room viewport was offscreen (cannot use sub-bitmap)
-	bool    IsOverlap = false;   // whether room viewport overlaps any others (marking dirty rects is complicated)
+	bool    IsOffscreen; // whether room viewport was offscreen (cannot use sub-bitmap)
+	bool    IsOverlap;   // whether room viewport overlaps any others (marking dirty rects is complicated)
 };
 
-
 // Converts AGS color index to the actual bitmap color using game's color depth
 int MakeColor(int color_index);
 
@@ -135,9 +121,9 @@ void construct_engine_overlay();
 void add_to_sprite_list(Engine::IDriverDependantBitmap *spp, int xx, int yy, int baseline, int trans, int sprNum, bool isWalkBehind = false);
 void tint_image(Shared::Bitmap *g, Shared::Bitmap *source, int red, int grn, int blu, int light_level, int luminance = 255);
 void draw_sprite_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Shared::Bitmap *image, bool src_has_alpha,
-	Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
+                               Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
 void draw_sprite_slot_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, int src_slot,
-	Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
+                                    Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
 void draw_gui_sprite(Shared::Bitmap *ds, int pic, int x, int y, bool use_alpha, Shared::BlendMode blend_mode);
 void draw_gui_sprite_v330(Shared::Bitmap *ds, int pic, int x, int y, bool use_alpha = true, Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha);
 // Render game on screen
diff --git a/engines/ags/engine/ac/draw_software.cpp b/engines/ags/engine/ac/draw_software.cpp
index e8cc26ebc5..7bec6d6c5d 100644
--- a/engines/ags/engine/ac/draw_software.cpp
+++ b/engines/ags/engine/ac/draw_software.cpp
@@ -46,7 +46,6 @@
 //
 //=============================================================================
 
-#include "ags/lib/std/utility.h"
 #include "ags/lib/std/vector.h"
 #include "ags/engine/ac/draw_software.h"
 #include "ags/shared/gfx/bitmap.h"
@@ -118,7 +117,6 @@ void DirtyRects::Reset() {
 		DirtyRows[i].numSpans = 0;
 }
 
-
 void dispose_invalid_regions(bool /* room_only */) {
 	_GP(RoomCamRects).clear();
 	_GP(RoomCamPositions).clear();
@@ -230,7 +228,7 @@ void invalidate_rect_on_surf(int x1, int y1, int x2, int y2, DirtyRects &rects)
 			dirtyRow[a].numSpans++;
 		} else {
 			// didn't fit in an existing span, and there are none spare
-			int nearestDist = 99999, nearestWas = -1, extendLeft = 0;
+			int nearestDist = 99999, nearestWas = -1, extendLeft = false;
 			int tleft, tright;
 			// find the nearest span, and enlarge that to include this rect
 			for (s = 0; s < dirtyRow[a].numSpans; s++) {
@@ -313,7 +311,7 @@ void update_invalid_region(Bitmap *ds, Bitmap *src, const DirtyRects &rects, boo
 		const int surf_height = rects.SurfaceSize.Height;
 		// TODO: is this IsMemoryBitmap check is still relevant?
 		// If bitmaps properties match and no transform required other than linear offset
-		if ((src->GetColorDepth() == ds->GetColorDepth()) && (ds->IsMemoryBitmap())) {
+		if (src->GetColorDepth() == ds->GetColorDepth()) {
 			const int bypp = src->GetBPP();
 			// do the fast memory copy
 			for (int i = 0; i < surf_height; i++) {
@@ -382,7 +380,7 @@ void update_black_invreg_and_reset(Bitmap *ds) {
 }
 
 void update_room_invreg_and_reset(int view_index, Bitmap *ds, Bitmap *src, bool no_transform) {
-	if (view_index < 0 || _GP(RoomCamRects).empty())
+	if (view_index < 0 || _GP(RoomCamRects).size() == 0)
 		return;
 
 	update_invalid_region(ds, src, _GP(RoomCamRects)[view_index], no_transform);
diff --git a/engines/ags/engine/ac/draw_software.h b/engines/ags/engine/ac/draw_software.h
index f8d3cc6a75..adda8e1e1c 100644
--- a/engines/ags/engine/ac/draw_software.h
+++ b/engines/ags/engine/ac/draw_software.h
@@ -27,8 +27,8 @@
 //
 //=============================================================================
 
-#ifndef AGS_ENGINE_AC_DRAWSOFTWARE_H
-#define AGS_ENGINE_AC_DRAWSOFTWARE_H
+#ifndef AGS_ENGINE_AC_DRAW_SOFTWARE_H
+#define AGS_ENGINE_AC_DRAW_SOFTWARE_H
 
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/engine/gfx/ddb.h"
diff --git a/engines/ags/engine/ac/drawingsurface.cpp b/engines/ags/engine/ac/drawing_surface.cpp
similarity index 75%
rename from engines/ags/engine/ac/drawingsurface.cpp
rename to engines/ags/engine/ac/drawing_surface.cpp
index d72e538382..3d5c1fe9f6 100644
--- a/engines/ags/engine/ac/drawingsurface.cpp
+++ b/engines/ags/engine/ac/drawing_surface.cpp
@@ -21,30 +21,28 @@
  */
 
 #include "ags/engine/ac/draw.h"
-#include "ags/engine/ac/drawingsurface.h"
+#include "ags/engine/ac/drawing_surface.h"
 #include "ags/shared/ac/common.h"
-#include "ags/engine/ac/charactercache.h"
+#include "ags/engine/ac/character_cache.h"
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/game.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_translation.h"
-#include "ags/engine/ac/objectcache.h"
-#include "ags/engine/ac/roomobject.h"
-#include "ags/engine/ac/roomstatus.h"
-#include "ags/engine/ac/runtime_defines.h"
+#include "ags/engine/ac/object_cache.h"
+#include "ags/engine/ac/room_object.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/ac/string.h"
-#include "ags/engine/ac/walkbehind.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/shared/font/fonts.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/shared/ac/spritecache.h"
-#include "ags/engine/script/runtimescriptvalue.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/shared/ac/sprite_cache.h"
+#include "ags/engine/script/runtime_script_value.h"
 #include "ags/shared/gfx/gfx_def.h"
-#include "ags/engine/gfx/gfx_util.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
+#include "ags/engine/gfx/gfx_util.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -66,33 +64,9 @@ void DrawingSurface_Release(ScriptDrawingSurface *sds) {
 
 		sds->roomBackgroundNumber = -1;
 	}
-	if (sds->roomMaskType > kRoomAreaNone) {
-		if (sds->roomMaskType == kRoomAreaWalkBehind) {
-			recache_walk_behinds();
-		}
-		sds->roomMaskType = kRoomAreaNone;
-	}
 	if (sds->dynamicSpriteNumber >= 0) {
 		if (sds->modified) {
-			int tt;
-			// force a refresh of any cached object or character images
-			if (_G(croom) != nullptr) {
-				for (tt = 0; tt < _G(croom)->numobj; tt++) {
-					if (_G(objs)[tt].num == sds->dynamicSpriteNumber)
-						_G(objcache)[tt].sppic = -31999;
-				}
-			}
-			for (tt = 0; tt < _GP(game).numcharacters; tt++) {
-				if (_G(charcache)[tt].sppic == sds->dynamicSpriteNumber)
-					_G(charcache)[tt].sppic = -31999;
-			}
-			for (tt = 0; tt < _GP(game).numgui; tt++) {
-				if ((_GP(guis)[tt].BgImage == sds->dynamicSpriteNumber) &&
-					(_GP(guis)[tt].IsDisplayed())) {
-					_G(guis_need_update) = 1;
-					break;
-				}
-			}
+			game_sprite_updated(sds->dynamicSpriteNumber);
 		}
 
 		sds->dynamicSpriteNumber = -1;
@@ -140,113 +114,82 @@ ScriptDrawingSurface *DrawingSurface_CreateCopy(ScriptDrawingSurface *sds) {
 	return nullptr;
 }
 
-void DrawingSurface_DrawImageImpl(ScriptDrawingSurface *sds, Bitmap *src, int dst_x, int dst_y, int trans, int dst_width, int dst_height,
-	int src_x, int src_y, int src_width, int src_height, int sprite_id, bool src_has_alpha) {
-	Bitmap *ds = sds->GetBitmapSurface();
-	if (src == ds)
-		quit("!DrawingSurface.DrawImage: cannot draw onto itself");
+void DrawingSurface_DrawSurface(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int translev) {
+	if ((translev < 0) || (translev > 99))
+		quit("!DrawingSurface.DrawSurface: invalid parameter (transparency must be 0-99)");
+
+	Bitmap *ds = target->StartDrawing();
+	Bitmap *surfaceToDraw = source->GetBitmapSurface();
+
+	if (surfaceToDraw == target->GetBitmapSurface())
+		quit("!DrawingSurface.DrawSurface: cannot draw surface onto itself");
+
+	if (translev == 0) {
+		// just draw it over the top, no transparency
+		ds->Blit(surfaceToDraw, 0, 0, 0, 0, surfaceToDraw->GetWidth(), surfaceToDraw->GetHeight());
+		target->FinishedDrawing();
+		return;
+	}
+
+	if (surfaceToDraw->GetColorDepth() <= 8)
+		quit("!DrawingSurface.DrawSurface: 256-colour surfaces cannot be drawn transparently");
+
+	// Draw it transparently
+	GfxUtil::DrawSpriteWithTransparency(ds, surfaceToDraw, 0, 0,
+	                                    GfxDef::Trans100ToAlpha255(translev));
+	target->FinishedDrawing();
+}
+
+void DrawingSurface_DrawImage(ScriptDrawingSurface *sds, int xx, int yy, int slot, int trans, int width, int height) {
+	if ((slot < 0) || (_GP(spriteset)[slot] == nullptr))
+		quit("!DrawingSurface.DrawImage: invalid sprite slot number specified");
+
 	if ((trans < 0) || (trans > 100))
 		quit("!DrawingSurface.DrawImage: invalid transparency setting");
 
+	// 100% transparency, don't draw anything
 	if (trans == 100)
-		return; // fully transparent
-	if (dst_width < 1 || dst_height < 1 || src_width < 1 || src_height < 1)
-		return; // invalid src or dest rectangles
+		return;
 
-	// Setup uninitialized arguments; convert coordinates for legacy script mode
-	if (dst_width == SCR_NO_VALUE) {
-		dst_width = src->GetWidth();
-	} else {
-		sds->SizeToGameResolution(&dst_width);
-	}
-	if (dst_height == SCR_NO_VALUE) {
-		dst_height = src->GetHeight();
-	} else {
-		sds->SizeToGameResolution(&dst_height);
-	}
+	Bitmap *sourcePic = _GP(spriteset)[slot];
+	bool needToFreeBitmap = false;
 
-	if (src_x == SCR_NO_VALUE) {
-		src_x = 0;
-	}
-	if (src_y == SCR_NO_VALUE) {
-		src_y = 0;
-	}
-	sds->PointToGameResolution(&src_x, &src_y);
-	if (src_width == SCR_NO_VALUE) {
-		src_width = src->GetWidth();
-	} else {
-		sds->SizeToGameResolution(&src_width);
-	}
-	if (src_height == SCR_NO_VALUE) {
-		src_height = src->GetHeight();
-	} else {
-		sds->SizeToGameResolution(&src_height);
-	}
+	if (width != SCR_NO_VALUE) {
+		// Resize specified
 
-	if (dst_x >= ds->GetWidth() || dst_x + dst_width <= 0 || dst_y >= ds->GetHeight() || dst_y + dst_height <= 0 ||
-		src_x >= src->GetWidth() || src_x + src_width <= 0 || src_y >= src->GetHeight() || src_y + src_height <= 0)
-		return; // source or destination rects lie completely off surface
-	// Clamp the source rect to the valid limits to prevent exceptions (ignore dest, bitmap drawing deals with that)
-	Math::ClampLength(src_x, src_width, 0, src->GetWidth());
-	Math::ClampLength(src_y, src_height, 0, src->GetHeight());
+		if ((width < 1) || (height < 1))
+			return;
 
-	// TODO: possibly optimize by not making a stretched intermediate bitmap
-	// if simplier blit/draw_sprite could be called (no translucency with alpha channel).
-	bool needToFreeBitmap = false;
-	if (dst_width != src->GetWidth() || dst_height != src->GetHeight() ||
-		src_width != src->GetWidth() || src_height != src->GetHeight()) {
-		// Resize and/or partial copy specified
-		Bitmap *newPic = BitmapHelper::CreateBitmap(dst_width, dst_height, src->GetColorDepth());
-		newPic->StretchBlt(src,
-			RectWH(src_x, src_y, src_width, src_height),
-			RectWH(0, 0, dst_width, dst_height));
-
-		src = newPic;
+		sds->SizeToGameResolution(&width, &height);
+
+		// resize the sprite to the requested size
+		Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, sourcePic->GetColorDepth());
+
+		newPic->StretchBlt(sourcePic,
+		                   RectWH(0, 0, _GP(game).SpriteInfos[slot].Width, _GP(game).SpriteInfos[slot].Height),
+		                   RectWH(0, 0, width, height));
+
+		sourcePic = newPic;
 		needToFreeBitmap = true;
 		update_polled_stuff_if_runtime();
 	}
 
-	ds = sds->StartDrawing();
-	sds->PointToGameResolution(&dst_x, &dst_y);
+	Bitmap *ds = sds->StartDrawing();
+	sds->PointToGameResolution(&xx, &yy);
 
-	if (src->GetColorDepth() != ds->GetColorDepth()) {
-		if (sprite_id >= 0)
-			debug_script_warn("DrawImage: Sprite %d colour depth %d-bit not same as background depth %d-bit", sprite_id, src->GetColorDepth(), ds->GetColorDepth());
-		else
-			debug_script_warn("DrawImage: Source image colour depth %d-bit not same as background depth %d-bit", src->GetColorDepth(), ds->GetColorDepth());
+	if (sourcePic->GetColorDepth() != ds->GetColorDepth()) {
+		debug_script_warn("RawDrawImage: Sprite %d colour depth %d-bit not same as background depth %d-bit", slot, _GP(spriteset)[slot]->GetColorDepth(), ds->GetColorDepth());
 	}
 
-	draw_sprite_support_alpha(ds, sds->hasAlphaChannel != 0, dst_x, dst_y, src, src_has_alpha,
-		kBlendMode_Alpha, GfxDef::Trans100ToAlpha255(trans));
+	draw_sprite_support_alpha(ds, sds->hasAlphaChannel != 0, xx, yy, sourcePic, (_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0,
+	                          kBlendMode_Alpha, GfxDef::Trans100ToAlpha255(trans));
 
 	sds->FinishedDrawing();
 
 	if (needToFreeBitmap)
-		delete src;
-}
-
-void DrawingSurface_DrawImageEx(ScriptDrawingSurface *sds, int dst_x, int dst_y, int slot, int trans, int dst_width, int dst_height,
-	int src_x, int src_y, int src_width, int src_height) {
-	if ((slot < 0) || (_GP(spriteset)[slot] == nullptr))
-		quit("!DrawingSurface.DrawImage: invalid sprite slot number specified");
-	DrawingSurface_DrawImageImpl(sds, _GP(spriteset)[slot], dst_x, dst_y, trans, dst_width, dst_height,
-		src_x, src_y, src_width, src_height, slot, (_GP(game).SpriteInfos[slot].Flags & SPF_ALPHACHANNEL) != 0);
-}
-
-void DrawingSurface_DrawImage(ScriptDrawingSurface *sds, int xx, int yy, int slot, int trans, int width, int height) {
-	DrawingSurface_DrawImageEx(sds, xx, yy, slot, trans, width, height, 0, 0, SCR_NO_VALUE, SCR_NO_VALUE);
+		delete sourcePic;
 }
 
-void DrawingSurface_DrawSurfaceEx(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int trans,
-	int dst_x, int dst_y, int dst_width, int dst_height,
-	int src_x, int src_y, int src_width, int src_height) {
-	DrawingSurface_DrawImageImpl(target, source->GetBitmapSurface(), dst_x, dst_y, trans, dst_width, dst_height,
-		src_x, src_y, src_width, src_height, -1, source->hasAlphaChannel);
-}
-
-void DrawingSurface_DrawSurface(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int trans) {
-	DrawingSurface_DrawSurfaceEx(target, source, trans, 0, 0, SCR_NO_VALUE, SCR_NO_VALUE, 0, 0, SCR_NO_VALUE, SCR_NO_VALUE);
-}
 
 void DrawingSurface_SetDrawingColor(ScriptDrawingSurface *sds, int newColour) {
 	sds->currentColourScript = newColour;
@@ -275,15 +218,17 @@ int DrawingSurface_GetUseHighResCoordinates(ScriptDrawingSurface *sds) {
 }
 
 int DrawingSurface_GetHeight(ScriptDrawingSurface *sds) {
-	Bitmap *ds = sds->GetBitmapSurface();
+	Bitmap *ds = sds->StartDrawing();
 	int height = ds->GetHeight();
+	sds->FinishedDrawingReadOnly();
 	sds->SizeToGameResolution(&height);
 	return height;
 }
 
 int DrawingSurface_GetWidth(ScriptDrawingSurface *sds) {
-	Bitmap *ds = sds->GetBitmapSurface();
+	Bitmap *ds = sds->StartDrawing();
 	int width = ds->GetWidth();
+	sds->FinishedDrawingReadOnly();
 	sds->SizeToGameResolution(&width);
 	return width;
 }
@@ -350,22 +295,22 @@ void DrawingSurface_DrawStringWrapped(ScriptDrawingSurface *sds, int xx, int yy,
 	sds->PointToGameResolution(&xx, &yy);
 	sds->SizeToGameResolution(&wid);
 
-	if (break_up_text_into_lines(msg, _GP(fontLines), wid, font) == 0)
+	if (break_up_text_into_lines(msg, Lines, wid, font) == 0)
 		return;
 
 	Bitmap *ds = sds->StartDrawing();
 	color_t text_color = sds->currentColour;
 
-	for (size_t i = 0; i < _GP(fontLines).Count(); i++) {
+	for (size_t i = 0; i < Lines.Count(); i++) {
 		int drawAtX = xx;
 
 		if (alignment & kMAlignHCenter) {
-			drawAtX = xx + ((wid / 2) - wgettextwidth(_GP(fontLines)[i], font) / 2);
+			drawAtX = xx + ((wid / 2) - wgettextwidth(Lines[i], font) / 2);
 		} else if (alignment & kMAlignRight) {
-			drawAtX = (xx + wid) - wgettextwidth(_GP(fontLines)[i], font);
+			drawAtX = (xx + wid) - wgettextwidth(Lines[i], font);
 		}
 
-		wouttext_outline(ds, drawAtX, yy + linespacing * i, font, text_color, _GP(fontLines)[i]);
+		wouttext_outline(ds, drawAtX, yy + linespacing * i, font, text_color, Lines[i]);
 	}
 
 	sds->FinishedDrawing();
@@ -459,15 +404,8 @@ RuntimeScriptValue Sc_DrawingSurface_DrawCircle(void *self, const RuntimeScriptV
 }
 
 // void (ScriptDrawingSurface* sds, int xx, int yy, int slot, int trans, int width, int height)
-RuntimeScriptValue Sc_DrawingSurface_DrawImage_6(void *self, const RuntimeScriptValue *params, int32_t param_count) {
-	API_OBJCALL_VOID_PINT6(ScriptDrawingSurface, DrawingSurface_DrawImage);
-}
-
 RuntimeScriptValue Sc_DrawingSurface_DrawImage(void *self, const RuntimeScriptValue *params, int32_t param_count) {
-	ASSERT_OBJ_PARAM_COUNT(METHOD, 10);
-	DrawingSurface_DrawImageEx((ScriptDrawingSurface *)self, params[0].IValue, params[1].IValue, params[2].IValue, params[3].IValue, params[4].IValue, params[5].IValue,
-		params[6].IValue, params[7].IValue, params[8].IValue, params[9].IValue);
-	return RuntimeScriptValue((int32_t)0);
+	API_OBJCALL_VOID_PINT6(ScriptDrawingSurface, DrawingSurface_DrawImage);
 }
 
 // void (ScriptDrawingSurface *sds, int fromx, int fromy, int tox, int toy, int thickness)
@@ -507,16 +445,8 @@ RuntimeScriptValue Sc_DrawingSurface_DrawStringWrapped(void *self, const Runtime
 }
 
 // void (ScriptDrawingSurface* target, ScriptDrawingSurface* source, int translev)
-RuntimeScriptValue Sc_DrawingSurface_DrawSurface_2(void *self, const RuntimeScriptValue *params, int32_t param_count) {
-	API_OBJCALL_VOID_POBJ_PINT(ScriptDrawingSurface, DrawingSurface_DrawSurface, ScriptDrawingSurface);
-}
-
 RuntimeScriptValue Sc_DrawingSurface_DrawSurface(void *self, const RuntimeScriptValue *params, int32_t param_count) {
-	ASSERT_OBJ_PARAM_COUNT(METHOD, 10);
-	DrawingSurface_DrawSurfaceEx((ScriptDrawingSurface *)self, (ScriptDrawingSurface *)params[0].Ptr,
-		params[1].IValue, params[2].IValue, params[3].IValue, params[4].IValue, params[5].IValue,
-		params[6].IValue, params[7].IValue, params[8].IValue, params[9].IValue);
-	return RuntimeScriptValue((int32_t)0);
+	API_OBJCALL_VOID_POBJ_PINT(ScriptDrawingSurface, DrawingSurface_DrawSurface, ScriptDrawingSurface);
 }
 
 // void (ScriptDrawingSurface *sds, int x1, int y1, int x2, int y2, int x3, int y3)
@@ -580,8 +510,7 @@ void RegisterDrawingSurfaceAPI(ScriptAPIVersion base_api, ScriptAPIVersion compa
 	ccAddExternalObjectFunction("DrawingSurface::Clear^1", Sc_DrawingSurface_Clear);
 	ccAddExternalObjectFunction("DrawingSurface::CreateCopy^0", Sc_DrawingSurface_CreateCopy);
 	ccAddExternalObjectFunction("DrawingSurface::DrawCircle^3", Sc_DrawingSurface_DrawCircle);
-	ccAddExternalObjectFunction("DrawingSurface::DrawImage^6", Sc_DrawingSurface_DrawImage_6);
-	ccAddExternalObjectFunction("DrawingSurface::DrawImage^10", Sc_DrawingSurface_DrawImage);
+	ccAddExternalObjectFunction("DrawingSurface::DrawImage^6", Sc_DrawingSurface_DrawImage);
 	ccAddExternalObjectFunction("DrawingSurface::DrawLine^5", Sc_DrawingSurface_DrawLine);
 	ccAddExternalObjectFunction("DrawingSurface::DrawMessageWrapped^5", Sc_DrawingSurface_DrawMessageWrapped);
 	ccAddExternalObjectFunction("DrawingSurface::DrawPixel^2", Sc_DrawingSurface_DrawPixel);
@@ -591,8 +520,7 @@ void RegisterDrawingSurfaceAPI(ScriptAPIVersion base_api, ScriptAPIVersion compa
 		ccAddExternalObjectFunction("DrawingSurface::DrawStringWrapped^6", Sc_DrawingSurface_DrawStringWrapped_Old);
 	else
 		ccAddExternalObjectFunction("DrawingSurface::DrawStringWrapped^6", Sc_DrawingSurface_DrawStringWrapped);
-	ccAddExternalObjectFunction("DrawingSurface::DrawSurface^2", Sc_DrawingSurface_DrawSurface_2);
-	ccAddExternalObjectFunction("DrawingSurface::DrawSurface^10", Sc_DrawingSurface_DrawSurface);
+	ccAddExternalObjectFunction("DrawingSurface::DrawSurface^2", Sc_DrawingSurface_DrawSurface);
 	ccAddExternalObjectFunction("DrawingSurface::DrawTriangle^6", Sc_DrawingSurface_DrawTriangle);
 	ccAddExternalObjectFunction("DrawingSurface::GetPixel^2", Sc_DrawingSurface_GetPixel);
 	ccAddExternalObjectFunction("DrawingSurface::Release^0", Sc_DrawingSurface_Release);
diff --git a/engines/ags/engine/ac/drawingsurface.h b/engines/ags/engine/ac/drawing_surface.h
similarity index 91%
rename from engines/ags/engine/ac/drawingsurface.h
rename to engines/ags/engine/ac/drawing_surface.h
index 7ba6a87c55..29343f7bec 100644
--- a/engines/ags/engine/ac/drawingsurface.h
+++ b/engines/ags/engine/ac/drawing_surface.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DRAWINGSURFACE_H
-#define AGS_ENGINE_AC_DRAWINGSURFACE_H
+#ifndef AGS_ENGINE_AC_DRAWING_SURFACE_H
+#define AGS_ENGINE_AC_DRAWING_SURFACE_H
 
-#include "ags/engine/ac/dynobj/scriptdrawingsurface.h"
+#include "ags/engine/ac/dynobj/script_drawing_surface.h"
 
 namespace AGS3 {
 
@@ -31,7 +31,7 @@ void    DrawingSurface_Release(ScriptDrawingSurface *sds);
 // convert actual co-ordinate back to what the script is expecting
 ScriptDrawingSurface *DrawingSurface_CreateCopy(ScriptDrawingSurface *sds);
 void    DrawingSurface_DrawSurface(ScriptDrawingSurface *target, ScriptDrawingSurface *source, int translev);
-void    DrawingSurface_DrawImage_FullSrc(ScriptDrawingSurface *sds, int xx, int yy, int slot, int trans, int width, int height);
+void    DrawingSurface_DrawImage(ScriptDrawingSurface *sds, int xx, int yy, int slot, int trans, int width, int height);
 void    DrawingSurface_SetDrawingColor(ScriptDrawingSurface *sds, int newColour);
 int     DrawingSurface_GetDrawingColor(ScriptDrawingSurface *sds);
 void    DrawingSurface_SetUseHighResCoordinates(ScriptDrawingSurface *sds, int highRes);
diff --git a/engines/ags/engine/ac/dynamicsprite.cpp b/engines/ags/engine/ac/dynamic_sprite.cpp
similarity index 93%
rename from engines/ags/engine/ac/dynamicsprite.cpp
rename to engines/ags/engine/ac/dynamic_sprite.cpp
index 79e12bbf45..2ec1358fee 100644
--- a/engines/ags/engine/ac/dynamicsprite.cpp
+++ b/engines/ags/engine/ac/dynamic_sprite.cpp
@@ -20,25 +20,28 @@
  *
  */
 
-#include "ags/engine/ac/dynamicsprite.h"
+#include "ags/lib/std/math.h"
+#include "ags/engine/ac/dynamic_sprite.h"
 #include "ags/shared/ac/common.h"
-#include "ags/engine/ac/charactercache.h"
+#include "ags/engine/ac/character_cache.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/global_dynamicsprite.h"
+#include "ags/engine/ac/game.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
+#include "ags/engine/ac/global_dynamic_sprite.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/math.h"    // M_PI
-#include "ags/engine/ac/objectcache.h"
+#include "ags/engine/ac/object_cache.h"
 #include "ags/engine/ac/path_helper.h"
-#include "ags/engine/ac/roomobject.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_object.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/ac/system.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/shared/game/roomstruct.h"
-#include "ags/shared/gui/guibutton.h"
-#include "ags/shared/ac/spritecache.h"
-#include "ags/engine/gfx/graphicsdriver.h"
-#include "ags/engine/script/runtimescriptvalue.h"
+#include "ags/shared/game/room_struct.h"
+#include "ags/shared/gui/gui_button.h"
+#include "ags/shared/ac/sprite_cache.h"
+#include "ags/engine/gfx/graphics_driver.h"
+#include "ags/engine/script/runtime_script_value.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
@@ -106,13 +109,14 @@ void DynamicSprite_Resize(ScriptDynamicSprite *sds, int width, int height) {
 	// resize the sprite to the requested size
 	Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, _GP(spriteset)[sds->slot]->GetColorDepth());
 	newPic->StretchBlt(_GP(spriteset)[sds->slot],
-		RectWH(0, 0, _GP(game).SpriteInfos[sds->slot].Width, _GP(game).SpriteInfos[sds->slot].Height),
-		RectWH(0, 0, width, height));
+	                   RectWH(0, 0, _GP(game).SpriteInfos[sds->slot].Width, _GP(game).SpriteInfos[sds->slot].Height),
+	                   RectWH(0, 0, width, height));
 
 	delete _GP(spriteset)[sds->slot];
 
 	// replace the bitmap in the sprite set
 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
+	game_sprite_updated(sds->slot);
 }
 
 void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction) {
@@ -135,6 +139,7 @@ void DynamicSprite_Flip(ScriptDynamicSprite *sds, int direction) {
 
 	// replace the bitmap in the sprite set
 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
+	game_sprite_updated(sds->slot);
 }
 
 void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite) {
@@ -142,7 +147,7 @@ void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSpri
 		quit("!DynamicSprite.CopyTransparencyMask: sprite has been deleted");
 
 	if ((_GP(game).SpriteInfos[sds->slot].Width != _GP(game).SpriteInfos[sourceSprite].Width) ||
-		(_GP(game).SpriteInfos[sds->slot].Height != _GP(game).SpriteInfos[sourceSprite].Height)) {
+	        (_GP(game).SpriteInfos[sds->slot].Height != _GP(game).SpriteInfos[sourceSprite].Height)) {
 		quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same size");
 	}
 
@@ -162,6 +167,7 @@ void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSpri
 	}
 
 	BitmapHelper::CopyTransparency(target, source, dst_has_alpha, src_has_alpha);
+	game_sprite_updated(sds->slot);
 }
 
 void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int height, int x, int y) {
@@ -181,6 +187,7 @@ void DynamicSprite_ChangeCanvasSize(ScriptDynamicSprite *sds, int width, int hei
 
 	// replace the bitmap in the sprite set
 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
+	game_sprite_updated(sds->slot);
 }
 
 void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x1, int y1, int width, int height) {
@@ -203,6 +210,7 @@ void DynamicSprite_Crop(ScriptDynamicSprite *sds, int x1, int y1, int width, int
 
 	// replace the bitmap in the sprite set
 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
+	game_sprite_updated(sds->slot);
 }
 
 void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int height) {
@@ -238,12 +246,13 @@ void DynamicSprite_Rotate(ScriptDynamicSprite *sds, int angle, int width, int he
 	// rotate the sprite about its centre
 	// (+ width%2 fixes one pixel offset problem)
 	newPic->RotateBlt(_GP(spriteset)[sds->slot], width / 2 + width % 2, height / 2,
-		_GP(game).SpriteInfos[sds->slot].Width / 2, _GP(game).SpriteInfos[sds->slot].Height / 2, itofix(angle));
+	                  _GP(game).SpriteInfos[sds->slot].Width / 2, _GP(game).SpriteInfos[sds->slot].Height / 2, itofix(angle));
 
 	delete _GP(spriteset)[sds->slot];
 
 	// replace the bitmap in the sprite set
 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
+	game_sprite_updated(sds->slot);
 }
 
 void DynamicSprite_Tint(ScriptDynamicSprite *sds, int red, int green, int blue, int saturation, int luminance) {
@@ -255,6 +264,7 @@ void DynamicSprite_Tint(ScriptDynamicSprite *sds, int red, int green, int blue,
 	delete source;
 	// replace the bitmap in the sprite set
 	add_dynamic_sprite(sds->slot, newPic, (_GP(game).SpriteInfos[sds->slot].Flags & SPF_ALPHACHANNEL) != 0);
+	game_sprite_updated(sds->slot);
 }
 
 int DynamicSprite_SaveToFile(ScriptDynamicSprite *sds, const char *namm) {
@@ -262,7 +272,7 @@ int DynamicSprite_SaveToFile(ScriptDynamicSprite *sds, const char *namm) {
 		quit("!DynamicSprite.SaveToFile: sprite has been deleted");
 
 	auto filename = String(namm);
-	if (filename.FindChar('.') == String::npos)
+	if (filename.FindChar('.') == (size_t)-1)
 		filename.Append(".bmp");
 
 	ResolvedPath rp;
@@ -405,7 +415,7 @@ ScriptDynamicSprite *DynamicSprite_CreateFromBackground(int frame, int x1, int y
 		width = _GP(play).room_width;
 		height = _GP(play).room_height;
 	} else if ((x1 < 0) || (y1 < 0) || (width < 1) || (height < 1) ||
-		(x1 + width > _GP(play).room_width) || (y1 + height > _GP(play).room_height))
+	           (x1 + width > _GP(play).room_width) || (y1 + height > _GP(play).room_height))
 		quit("!DynamicSprite.CreateFromBackground: invalid co-ordinates specified");
 
 	data_to_game_coords(&x1, &y1);
@@ -448,9 +458,8 @@ void add_dynamic_sprite(int gotSlot, Bitmap *redin, bool hasAlpha) {
 }
 
 void free_dynamic_sprite(int gotSlot) {
-	int tt;
 
-	if ((gotSlot < 0) || (gotSlot >= _GP(spriteset).GetSpriteSlotCount()))
+	if ((gotSlot < 0) || ((size_t)gotSlot >= _GP(spriteset).GetSpriteSlotCount()))
 		quit("!FreeDynamicSprite: invalid slot number");
 
 	if ((_GP(game).SpriteInfos[gotSlot].Flags & SPF_DYNAMICALLOC) == 0)
@@ -462,30 +471,7 @@ void free_dynamic_sprite(int gotSlot) {
 	_GP(game).SpriteInfos[gotSlot].Width = 0;
 	_GP(game).SpriteInfos[gotSlot].Height = 0;
 
-	// ensure it isn't still on any GUI buttons
-	for (tt = 0; tt < _G(numguibuts); tt++) {
-		if (_GP(guibuts)[tt].IsDeleted())
-			continue;
-		if (_GP(guibuts)[tt].Image == gotSlot)
-			_GP(guibuts)[tt].Image = 0;
-		if (_GP(guibuts)[tt].CurrentImage == gotSlot)
-			_GP(guibuts)[tt].CurrentImage = 0;
-		if (_GP(guibuts)[tt].MouseOverImage == gotSlot)
-			_GP(guibuts)[tt].MouseOverImage = 0;
-		if (_GP(guibuts)[tt].PushedImage == gotSlot)
-			_GP(guibuts)[tt].PushedImage = 0;
-	}
-
-	// force refresh of any object caches using the sprite
-	if (_G(croom) != nullptr) {
-		for (tt = 0; tt < _G(croom)->numobj; tt++) {
-			if (_G(objs)[tt].num == gotSlot) {
-				_G(objs)[tt].num = 0;
-				_G(objcache)[tt].sppic = -1;
-			} else if (_G(objcache)[tt].sppic == gotSlot)
-				_G(objcache)[tt].sppic = -1;
-		}
-	}
+	game_sprite_deleted(gotSlot);
 }
 
 //=============================================================================
diff --git a/engines/ags/engine/ac/dynamicsprite.h b/engines/ags/engine/ac/dynamic_sprite.h
similarity index 96%
rename from engines/ags/engine/ac/dynamicsprite.h
rename to engines/ags/engine/ac/dynamic_sprite.h
index 478407d22a..12355fb6e2 100644
--- a/engines/ags/engine/ac/dynamicsprite.h
+++ b/engines/ags/engine/ac/dynamic_sprite.h
@@ -23,8 +23,8 @@
 #ifndef AGS_ENGINE_AC_DYNAMICSPRITE_H
 #define AGS_ENGINE_AC_DYNAMICSPRITE_H
 
-#include "ags/engine/ac/dynobj/scriptdynamicsprite.h"
-#include "ags/engine/ac/dynobj/scriptdrawingsurface.h"
+#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
+#include "ags/engine/ac/dynobj/script_drawing_surface.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/all_dynamicclasses.h b/engines/ags/engine/ac/dynobj/all_dynamic_classes.h
similarity index 81%
rename from engines/ags/engine/ac/dynobj/all_dynamicclasses.h
rename to engines/ags/engine/ac/dynobj/all_dynamic_classes.h
index da01ed1ce1..3e8c1887da 100644
--- a/engines/ags/engine/ac/dynobj/all_dynamicclasses.h
+++ b/engines/ags/engine/ac/dynobj/all_dynamic_classes.h
@@ -20,21 +20,20 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_ALLDYNAMICCLASSES_H
-#define AGS_ENGINE_AC_DYNOBJ_ALLDYNAMICCLASSES_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_ALL_DYNAMIC_CLASSES_H
+#define AGS_ENGINE_AC_DYNOBJ_ALL_DYNAMIC_CLASSES_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
-#include "ags/engine/ac/dynobj/cc_audiochannel.h"
-#include "ags/engine/ac/dynobj/cc_audioclip.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
+#include "ags/engine/ac/dynobj/cc_audio_channel.h"
+#include "ags/engine/ac/dynobj/cc_audio_clip.h"
 #include "ags/engine/ac/dynobj/cc_character.h"
 #include "ags/engine/ac/dynobj/cc_dialog.h"
 #include "ags/engine/ac/dynobj/cc_gui.h"
-#include "ags/engine/ac/dynobj/cc_guiobject.h"
+#include "ags/engine/ac/dynobj/cc_gui_object.h"
 #include "ags/engine/ac/dynobj/cc_hotspot.h"
 #include "ags/engine/ac/dynobj/cc_inventory.h"
 #include "ags/engine/ac/dynobj/cc_object.h"
 #include "ags/engine/ac/dynobj/cc_region.h"
-
 #include "ags/engine/ac/dynobj/cc_serializer.h"
 
 #endif
diff --git a/engines/ags/engine/ac/dynobj/all_script_classes.h b/engines/ags/engine/ac/dynobj/all_script_classes.h
new file mode 100644
index 0000000000..a03b6efc42
--- /dev/null
+++ b/engines/ags/engine/ac/dynobj/all_script_classes.h
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef AGS_ENGINE_AC_DYNOBJ_ALL_SCRIPT_CLASSES_H
+#define AGS_ENGINE_AC_DYNOBJ_ALL_SCRIPT_CLASSES_H
+
+#include "ags/engine/ac/dynobj/script_date_time.h"
+#include "ags/engine/ac/dynobj/script_dialog.h"
+#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
+#include "ags/engine/ac/dynobj/script_drawing_surface.h"
+#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
+#include "ags/engine/ac/dynobj/script_gui.h"
+#include "ags/engine/ac/dynobj/script_hotspot.h"
+#include "ags/engine/ac/dynobj/script_inv_item.h"
+#include "ags/engine/ac/dynobj/script_mouse.h"
+#include "ags/engine/ac/dynobj/script_object.h"
+#include "ags/engine/ac/dynobj/script_overlay.h"
+#include "ags/engine/ac/dynobj/script_region.h"
+#include "ags/engine/ac/dynobj/script_string.h"
+#include "ags/engine/ac/dynobj/script_system.h"
+#include "ags/engine/ac/dynobj/script_view_frame.h"
+
+#endif
diff --git a/engines/ags/engine/ac/dynobj/all_scriptclasses.h b/engines/ags/engine/ac/dynobj/all_scriptclasses.h
deleted file mode 100644
index 5d533fa9b9..0000000000
--- a/engines/ags/engine/ac/dynobj/all_scriptclasses.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AGS_ENGINE_AC_DYNOBJ_ALLSCRIPTCLASSES_H
-#define AGS_ENGINE_AC_DYNOBJ_ALLSCRIPTCLASSES_H
-
-#include "ags/engine/ac/dynobj/scriptdatetime.h"
-#include "ags/engine/ac/dynobj/scriptdialog.h"
-#include "ags/engine/ac/dynobj/scriptdialogoptionsrendering.h"
-#include "ags/engine/ac/dynobj/scriptdrawingsurface.h"
-#include "ags/engine/ac/dynobj/scriptdynamicsprite.h"
-#include "ags/engine/ac/dynobj/scriptgui.h"
-#include "ags/engine/ac/dynobj/scripthotspot.h"
-#include "ags/engine/ac/dynobj/scriptinvitem.h"
-#include "ags/engine/ac/dynobj/scriptmouse.h"
-#include "ags/engine/ac/dynobj/scriptobject.h"
-#include "ags/engine/ac/dynobj/scriptoverlay.h"
-#include "ags/engine/ac/dynobj/scriptregion.h"
-#include "ags/engine/ac/dynobj/scriptstring.h"
-#include "ags/engine/ac/dynobj/scriptsystem.h"
-#include "ags/engine/ac/dynobj/scriptviewframe.h"
-
-#endif
diff --git a/engines/ags/engine/ac/dynobj/cc_agsdynamicobject.cpp b/engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.cpp
similarity index 96%
rename from engines/ags/engine/ac/dynobj/cc_agsdynamicobject.cpp
rename to engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.cpp
index 43faf81a56..197e4a8f33 100644
--- a/engines/ags/engine/ac/dynobj/cc_agsdynamicobject.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.cpp
@@ -20,8 +20,9 @@
  *
  */
 
+//include <string.h>
 #include "ags/shared/core/types.h"
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 #include "ags/shared/ac/common.h"               // quit()
 #include "ags/shared/util/bbop.h"
 
@@ -69,7 +70,7 @@ int AGSCCDynamicObject::UnserializeInt() {
 	if (bytesSoFar >= totalBytes)
 		quit("Unserialise: internal error: read past EOF");
 
-	const char *chptr = &serbuffer[bytesSoFar];
+	char *chptr = &serbuffer[bytesSoFar];
 	bytesSoFar += 4;
 	return BBOp::Int32FromLE(*((const int *)chptr));
 }
@@ -78,7 +79,7 @@ float AGSCCDynamicObject::UnserializeFloat() {
 	if (bytesSoFar >= totalBytes)
 		quit("Unserialise: internal error: read past EOF");
 
-	const char *chptr = &serbuffer[bytesSoFar];
+	char *chptr = &serbuffer[bytesSoFar];
 	bytesSoFar += 4;
 	return BBOp::FloatFromLE(*((const float *)chptr));
 }
diff --git a/engines/ags/engine/ac/dynobj/cc_agsdynamicobject.h b/engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.h
similarity index 94%
rename from engines/ags/engine/ac/dynobj/cc_agsdynamicobject.h
rename to engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.h
index c7e16d6010..9aca1c78a6 100644
--- a/engines/ags/engine/ac/dynobj/cc_agsdynamicobject.h
+++ b/engines/ags/engine/ac/dynobj/cc_ags_dynamic_object.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CC_AGSDYNAMICOBJECT_H
-#define AGS_ENGINE_AC_DYNOBJ_CC_AGSDYNAMICOBJECT_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CCDYNAMIC_OBJECT_H
+#define AGS_ENGINE_AC_DYNOBJ_CCDYNAMIC_OBJECT_H
 
-#include "ags/engine/ac/dynobj/cc_dynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_audiochannel.cpp b/engines/ags/engine/ac/dynobj/cc_audio_channel.cpp
similarity index 89%
rename from engines/ags/engine/ac/dynobj/cc_audiochannel.cpp
rename to engines/ags/engine/ac/dynobj/cc_audio_channel.cpp
index c4faca4cd2..6aa9480f75 100644
--- a/engines/ags/engine/ac/dynobj/cc_audiochannel.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_audio_channel.cpp
@@ -20,8 +20,8 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/cc_audiochannel.h"
-#include "ags/engine/ac/dynobj/scriptaudiochannel.h"
+#include "ags/engine/ac/dynobj/cc_audio_channel.h"
+#include "ags/engine/ac/dynobj/script_audio_channel.h"
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/globals.h"
 
@@ -32,7 +32,7 @@ const char *CCAudioChannel::GetType() {
 }
 
 int CCAudioChannel::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptAudioChannel *ach = (ScriptAudioChannel *)const_cast<char *>(address);
+	const ScriptAudioChannel *ach = (const ScriptAudioChannel *)address;
 	StartSerialize(buffer);
 	SerializeInt(ach->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_audiochannel.h b/engines/ags/engine/ac/dynobj/cc_audio_channel.h
similarity index 89%
rename from engines/ags/engine/ac/dynobj/cc_audiochannel.h
rename to engines/ags/engine/ac/dynobj/cc_audio_channel.h
index 0013e82252..bd5b6eb23d 100644
--- a/engines/ags/engine/ac/dynobj/cc_audiochannel.h
+++ b/engines/ags/engine/ac/dynobj/cc_audio_channel.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CC_AUDIOCHANNEL_H
-#define AGS_ENGINE_AC_DYNOBJ_CC_AUDIOCHANNEL_H
+#ifndef AGS_ENGINE_DYNOBJ__CCAUDIOCHANNEL_H
+#define AGS_ENGINE_DYNOBJ__CCAUDIOCHANNEL_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_audioclip.cpp b/engines/ags/engine/ac/dynobj/cc_audio_clip.cpp
similarity index 85%
rename from engines/ags/engine/ac/dynobj/cc_audioclip.cpp
rename to engines/ags/engine/ac/dynobj/cc_audio_clip.cpp
index c686767542..e0b69cdd90 100644
--- a/engines/ags/engine/ac/dynobj/cc_audioclip.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_audio_clip.cpp
@@ -20,19 +20,20 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/cc_audioclip.h"
-#include "ags/shared/ac/dynobj/scriptaudioclip.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/globals.h"
+#include "ags/engine/ac/dynobj/cc_audio_clip.h"
+#include "ags/shared/ac/dynobj/script_audio_clip.h"
+#include "ags/shared/ac/game_setup_struct.h"
 
 namespace AGS3 {
 
+
+
 const char *CCAudioClip::GetType() {
 	return "AudioClip";
 }
 
 int CCAudioClip::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptAudioClip *ach = (ScriptAudioClip *)const_cast<char *>(address);
+	const ScriptAudioClip *ach = (const ScriptAudioClip *)address;
 	StartSerialize(buffer);
 	SerializeInt(ach->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_audioclip.h b/engines/ags/engine/ac/dynobj/cc_audio_clip.h
similarity index 89%
rename from engines/ags/engine/ac/dynobj/cc_audioclip.h
rename to engines/ags/engine/ac/dynobj/cc_audio_clip.h
index 32d2b8aa49..7af1694ba8 100644
--- a/engines/ags/engine/ac/dynobj/cc_audioclip.h
+++ b/engines/ags/engine/ac/dynobj/cc_audio_clip.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCAUDIOCLIP_H
-#define AGS_ENGINE_AC_DYNOBJ_CCAUDIOCLIP_H
+#ifndef AGS_ENGINE_DYNOBJ_CC_AUDIO_CLIP_H
+#define AGS_ENGINE_DYNOBJ_CC_AUDIO_CLIP_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_character.cpp b/engines/ags/engine/ac/dynobj/cc_character.cpp
index ac90043766..fca311d400 100644
--- a/engines/ags/engine/ac/dynobj/cc_character.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_character.cpp
@@ -21,14 +21,16 @@
  */
 
 #include "ags/engine/ac/dynobj/cc_character.h"
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/engine/ac/global_character.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/shared/ac/game_version.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
 
+
+
 // return the type name of the object
 const char *CCCharacter::GetType() {
 	return "Character";
@@ -37,7 +39,7 @@ const char *CCCharacter::GetType() {
 // serialize the object into BUFFER (which is BUFSIZE bytes)
 // return number of bytes used
 int CCCharacter::Serialize(const char *address, char *buffer, int bufsize) {
-	CharacterInfo *chaa = (CharacterInfo *)const_cast<char *>(address);
+	const CharacterInfo *chaa = (const CharacterInfo *)address;
 	StartSerialize(buffer);
 	SerializeInt(chaa->index_id);
 	return EndSerialize();
@@ -57,7 +59,7 @@ void CCCharacter::WriteInt16(const char *address, intptr_t offset, int16_t val)
 	// inventory for older games that reply on the previous behaviour.
 	if (_G(loaded_game_file_version) < kGameVersion_270) {
 		const int invoffset = 112;
-		if (offset >= invoffset && offset < (int)(invoffset + MAX_INV * sizeof(short))) {
+		if (offset >= invoffset && offset < (intptr_t)(invoffset + MAX_INV * sizeof(short))) {
 			update_invorder();
 		}
 	}
diff --git a/engines/ags/engine/ac/dynobj/cc_character.h b/engines/ags/engine/ac/dynobj/cc_character.h
index 8c800ec846..3f38155c4f 100644
--- a/engines/ags/engine/ac/dynobj/cc_character.h
+++ b/engines/ags/engine/ac/dynobj/cc_character.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCCHARACTER_H
-#define AGS_ENGINE_AC_DYNOBJ_CCCHARACTER_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CC_CHARACTER_H
+#define AGS_ENGINE_AC_DYNOBJ_CC_CHARACTER_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_dialog.cpp b/engines/ags/engine/ac/dynobj/cc_dialog.cpp
index db7cb37724..caa38690f2 100644
--- a/engines/ags/engine/ac/dynobj/cc_dialog.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_dialog.cpp
@@ -22,8 +22,8 @@
 
 #include "ags/engine/ac/dynobj/cc_dialog.h"
 #include "ags/engine/ac/dialog.h"
-#include "ags/shared/ac/dialogtopic.h"
-#include "ags/shared/ac/gamestructdefines.h"
+#include "ags/shared/ac/dialog_topic.h"
+#include "ags/shared/ac/game_struct_defines.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -36,7 +36,7 @@ const char *CCDialog::GetType() {
 // serialize the object into BUFFER (which is BUFSIZE bytes)
 // return number of bytes used
 int CCDialog::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptDialog *shh = (ScriptDialog *)const_cast<char *>(address);
+	const ScriptDialog *shh = (const ScriptDialog *)address;
 	StartSerialize(buffer);
 	SerializeInt(shh->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_dialog.h b/engines/ags/engine/ac/dynobj/cc_dialog.h
index 061892734d..8074cf3dcd 100644
--- a/engines/ags/engine/ac/dynobj/cc_dialog.h
+++ b/engines/ags/engine/ac/dynobj/cc_dialog.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCDIALOG_H
-#define AGS_ENGINE_AC_DYNOBJ_CCDIALOG_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CC_DIALOG_H
+#define AGS_ENGINE_AC_DYNOBJ_CC_DIALOG_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamicarray.cpp b/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
similarity index 98%
rename from engines/ags/engine/ac/dynobj/cc_dynamicarray.cpp
rename to engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
index 72d7df6635..dacec6d73f 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamicarray.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/cc_dynamicarray.h"
+#include "ags/engine/ac/dynobj/cc_dynamic_array.h"
 #include  "ags/globals.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamicarray.h b/engines/ags/engine/ac/dynobj/cc_dynamic_array.h
similarity index 93%
rename from engines/ags/engine/ac/dynobj/cc_dynamicarray.h
rename to engines/ags/engine/ac/dynobj/cc_dynamic_array.h
index 62ac557b93..5caa453075 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamicarray.h
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_array.h
@@ -20,11 +20,11 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCDYNAMICARRAY_H
-#define AGS_ENGINE_AC_DYNOBJ_CCDYNAMICARRAY_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CC_DYNAMICARRAY_H
+#define AGS_ENGINE_AC_DYNOBJ_CC_DYNAMICARRAY_H
 
 #include "ags/lib/std/vector.h"
-#include "ags/engine/ac/dynobj/cc_dynamicobject.h"   // ICCDynamicObject
+#include "ags/engine/ac/dynobj/cc_dynamic_object.h"   // ICCDynamicObject
 
 namespace AGS3 {
 
@@ -32,8 +32,6 @@ namespace AGS3 {
 #define ARRAY_MANAGED_TYPE_FLAG    0x80000000
 
 struct CCDynamicArray final : ICCDynamicObject {
-	virtual ~CCDynamicArray() {}
-
 	// return the type name of the object
 	const char *GetType() override;
 	int Dispose(const char *address, bool force) override;
@@ -60,10 +58,8 @@ struct CCDynamicArray final : ICCDynamicObject {
 
 // Helper functions for setting up dynamic arrays.
 namespace DynamicArrayHelpers {
-
 // Create array of managed strings
 DynObjectRef CreateStringArray(const std::vector<const char *>);
-
 } // namespace DynamicArrayHelpers
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamicobject.cpp b/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
similarity index 95%
rename from engines/ags/engine/ac/dynobj/cc_dynamicobject.cpp
rename to engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
index a107b6bea5..e00ed0e7aa 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamicobject.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
@@ -36,8 +36,10 @@
 
 //#define DEBUG_MANAGED_OBJECTS
 
-#include "ags/engine/ac/dynobj/cc_dynamicobject.h"
-#include "ags/engine/ac/dynobj/managedobjectpool.h"
+//include <stdlib.h>
+//include <string.h>
+#include "ags/engine/ac/dynobj/cc_dynamic_object.h"
+#include "ags/engine/ac/dynobj/managed_object_pool.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/shared/script/cc_error.h"
 #include "ags/shared/script/script_common.h"
@@ -59,7 +61,7 @@ int32_t ccRegisterManagedObject(const void *object, ICCDynamicObject *callback,
 	int32_t handl = _GP(pool).AddObject((const char *)object, callback, plugin_object);
 
 	ManagedObjectLog("Register managed object type '%s' handle=%d addr=%08X",
-		((callback == NULL) ? "(unknown)" : callback->GetType()), handl, object);
+	                 ((callback == NULL) ? "(unknown)" : callback->GetType()), handl, object);
 
 	return handl;
 }
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamicobject.h b/engines/ags/engine/ac/dynobj/cc_dynamic_object.h
similarity index 98%
rename from engines/ags/engine/ac/dynobj/cc_dynamicobject.h
rename to engines/ags/engine/ac/dynobj/cc_dynamic_object.h
index 552f34c376..a210c8ad52 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamicobject.h
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_object.h
@@ -26,8 +26,8 @@
 //
 //=============================================================================
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCDYNAMICOBJECT_H
-#define AGS_ENGINE_AC_DYNOBJ_CCDYNAMICOBJECT_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CC_DYNAMIC_OBJECT_H
+#define AGS_ENGINE_AC_DYNOBJ_CC_DYNAMIC_OBJECT_H
 
 #include "ags/lib/std/utility.h"
 #include "ags/shared/core/types.h"
@@ -100,6 +100,7 @@ struct ICCObjectReader {
 	// TODO: pass savegame format version
 	virtual void Unserialize(int index, const char *objectType, const char *serializedData, int dataSize) = 0;
 };
+
 struct ICCStringClass {
 	virtual ~ICCStringClass() {}
 	virtual DynObjectRef CreateString(const char *fromText) = 0;
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamicobject_addr_and_manager.h b/engines/ags/engine/ac/dynobj/cc_dynamic_object_addr_and_manager.h
similarity index 87%
rename from engines/ags/engine/ac/dynobj/cc_dynamicobject_addr_and_manager.h
rename to engines/ags/engine/ac/dynobj/cc_dynamic_object_addr_and_manager.h
index 91830bee0e..543e1636b7 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamicobject_addr_and_manager.h
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_object_addr_and_manager.h
@@ -23,13 +23,13 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_ADDR_AND_MANAGER_H
 #define AGS_ENGINE_AC_DYNOBJ_ADDR_AND_MANAGER_H
 
-#include "ags/engine/script/runtimescriptvalue.h"
-#include "ags/engine/ac/dynobj/cc_dynamicobject.h"
+#include "ags/engine/script/runtime_script_value.h"
+#include "ags/engine/ac/dynobj/cc_dynamic_object.h"
 
 namespace AGS3 {
 
 extern ScriptValueType ccGetObjectAddressAndManagerFromHandle(
-	int32_t handle, void *&object, ICCDynamicObject *&manager);
+    int32_t handle, void *&object, ICCDynamicObject *&manager);
 
 } // namespace AGS3
 
diff --git a/engines/ags/engine/ac/dynobj/cc_gui.cpp b/engines/ags/engine/ac/dynobj/cc_gui.cpp
index 6e3826937b..30d2acc213 100644
--- a/engines/ags/engine/ac/dynobj/cc_gui.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_gui.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "ags/engine/ac/dynobj/cc_gui.h"
-#include "ags/engine/ac/dynobj/scriptgui.h"
+#include "ags/engine/ac/dynobj/script_gui.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -34,7 +34,7 @@ const char *CCGUI::GetType() {
 // serialize the object into BUFFER (which is BUFSIZE bytes)
 // return number of bytes used
 int CCGUI::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptGUI *shh = (ScriptGUI *)const_cast<char *>(address);
+	const ScriptGUI *shh = (const ScriptGUI *)address;
 	StartSerialize(buffer);
 	SerializeInt(shh->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_gui.h b/engines/ags/engine/ac/dynobj/cc_gui.h
index 311684d656..cb4e2d4c82 100644
--- a/engines/ags/engine/ac/dynobj/cc_gui.h
+++ b/engines/ags/engine/ac/dynobj/cc_gui.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_CCGUI_H
 #define AGS_ENGINE_AC_DYNOBJ_CCGUI_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_guiobject.cpp b/engines/ags/engine/ac/dynobj/cc_gui_object.cpp
similarity index 91%
rename from engines/ags/engine/ac/dynobj/cc_guiobject.cpp
rename to engines/ags/engine/ac/dynobj/cc_gui_object.cpp
index b8fe19bac6..b41ae302fa 100644
--- a/engines/ags/engine/ac/dynobj/cc_guiobject.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_gui_object.cpp
@@ -20,10 +20,10 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/cc_guiobject.h"
-#include "ags/engine/ac/dynobj/scriptgui.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/shared/gui/guiobject.h"
+#include "ags/engine/ac/dynobj/cc_gui_object.h"
+#include "ags/engine/ac/dynobj/script_gui.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/shared/gui/gui_object.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/dynobj/cc_guiobject.h b/engines/ags/engine/ac/dynobj/cc_gui_object.h
similarity index 90%
rename from engines/ags/engine/ac/dynobj/cc_guiobject.h
rename to engines/ags/engine/ac/dynobj/cc_gui_object.h
index 6f1911e867..61f1eb6324 100644
--- a/engines/ags/engine/ac/dynobj/cc_guiobject.h
+++ b/engines/ags/engine/ac/dynobj/cc_gui_object.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCGUIOBJECT_H
-#define AGS_ENGINE_AC_DYNOBJ_CCGUIOBJECT_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CC_GUI_OBJECT_H
+#define AGS_ENGINE_AC_DYNOBJ_CC_GUI_OBJECT_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_hotspot.cpp b/engines/ags/engine/ac/dynobj/cc_hotspot.cpp
index e3581760e8..f9d9cefee3 100644
--- a/engines/ags/engine/ac/dynobj/cc_hotspot.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_hotspot.cpp
@@ -21,9 +21,9 @@
  */
 
 #include "ags/engine/ac/dynobj/cc_hotspot.h"
-#include "ags/engine/ac/dynobj/scripthotspot.h"
+#include "ags/engine/ac/dynobj/script_hotspot.h"
 #include "ags/shared/ac/common_defines.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -36,7 +36,7 @@ const char *CCHotspot::GetType() {
 // serialize the object into BUFFER (which is BUFSIZE bytes)
 // return number of bytes used
 int CCHotspot::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptHotspot *shh = (ScriptHotspot *)const_cast<char *>(address);
+	const ScriptHotspot *shh = (const ScriptHotspot *)address;
 	StartSerialize(buffer);
 	SerializeInt(shh->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_hotspot.h b/engines/ags/engine/ac/dynobj/cc_hotspot.h
index 1677a49295..24db996ded 100644
--- a/engines/ags/engine/ac/dynobj/cc_hotspot.h
+++ b/engines/ags/engine/ac/dynobj/cc_hotspot.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCHOTSPOT_H
-#define AGS_ENGINE_AC_DYNOBJ_CCHOTSPOT_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CC_HOTSPOT_H
+#define AGS_ENGINE_AC_DYNOBJ_CC_HOTSPOT_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_inventory.cpp b/engines/ags/engine/ac/dynobj/cc_inventory.cpp
index b95627943a..5509afdf2b 100644
--- a/engines/ags/engine/ac/dynobj/cc_inventory.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_inventory.cpp
@@ -21,8 +21,8 @@
  */
 
 #include "ags/engine/ac/dynobj/cc_inventory.h"
-#include "ags/engine/ac/dynobj/scriptinvitem.h"
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/engine/ac/dynobj/script_inv_item.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -35,7 +35,7 @@ const char *CCInventory::GetType() {
 // serialize the object into BUFFER (which is BUFSIZE bytes)
 // return number of bytes used
 int CCInventory::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptInvItem *shh = (ScriptInvItem *)const_cast<char *>(address);
+	const ScriptInvItem *shh = (const ScriptInvItem *)address;
 	StartSerialize(buffer);
 	SerializeInt(shh->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_inventory.h b/engines/ags/engine/ac/dynobj/cc_inventory.h
index 0687ebb54c..aa198b0580 100644
--- a/engines/ags/engine/ac/dynobj/cc_inventory.h
+++ b/engines/ags/engine/ac/dynobj/cc_inventory.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_CCINVENTORY_H
 #define AGS_ENGINE_AC_DYNOBJ_CCINVENTORY_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_object.cpp b/engines/ags/engine/ac/dynobj/cc_object.cpp
index d67bf9e6d7..04af35d29b 100644
--- a/engines/ags/engine/ac/dynobj/cc_object.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_object.cpp
@@ -21,9 +21,9 @@
  */
 
 #include "ags/engine/ac/dynobj/cc_object.h"
-#include "ags/engine/ac/dynobj/scriptobject.h"
+#include "ags/engine/ac/dynobj/script_object.h"
 #include "ags/shared/ac/common_defines.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -36,7 +36,7 @@ const char *CCObject::GetType() {
 // serialize the object into BUFFER (which is BUFSIZE bytes)
 // return number of bytes used
 int CCObject::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptObject *shh = (ScriptObject *)const_cast<char *>(address);
+	const ScriptObject *shh = (const ScriptObject *)address;
 	StartSerialize(buffer);
 	SerializeInt(shh->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_object.h b/engines/ags/engine/ac/dynobj/cc_object.h
index a6d77cc759..d0709081a4 100644
--- a/engines/ags/engine/ac/dynobj/cc_object.h
+++ b/engines/ags/engine/ac/dynobj/cc_object.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_CCOBJECT_H
 #define AGS_ENGINE_AC_DYNOBJ_CCOBJECT_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/cc_region.cpp b/engines/ags/engine/ac/dynobj/cc_region.cpp
index eae1c5d718..50e7f9bb36 100644
--- a/engines/ags/engine/ac/dynobj/cc_region.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_region.cpp
@@ -21,9 +21,9 @@
  */
 
 #include "ags/engine/ac/dynobj/cc_region.h"
-#include "ags/engine/ac/dynobj/scriptregion.h"
+#include "ags/engine/ac/dynobj/script_region.h"
 #include "ags/shared/ac/common_defines.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -36,7 +36,7 @@ const char *CCRegion::GetType() {
 // serialize the object into BUFFER (which is BUFSIZE bytes)
 // return number of bytes used
 int CCRegion::Serialize(const char *address, char *buffer, int bufsize) {
-	ScriptRegion *shh = (ScriptRegion *)const_cast<char *>(address);
+	const ScriptRegion *shh = (const ScriptRegion *)address;
 	StartSerialize(buffer);
 	SerializeInt(shh->id);
 	return EndSerialize();
diff --git a/engines/ags/engine/ac/dynobj/cc_region.h b/engines/ags/engine/ac/dynobj/cc_region.h
index 927b2e874b..87207ae975 100644
--- a/engines/ags/engine/ac/dynobj/cc_region.h
+++ b/engines/ags/engine/ac/dynobj/cc_region.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_CCREGION_H
 #define AGS_ENGINE_AC_DYNOBJ_CCREGION_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
@@ -37,6 +37,7 @@ struct CCRegion final : AGSCCDynamicObject {
 	int Serialize(const char *address, char *buffer, int bufsize) override;
 
 	void Unserialize(int index, const char *serializedData, int dataSize) override;
+
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/cc_serializer.cpp b/engines/ags/engine/ac/dynobj/cc_serializer.cpp
index dc6149505f..1f9f633630 100644
--- a/engines/ags/engine/ac/dynobj/cc_serializer.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_serializer.cpp
@@ -20,18 +20,19 @@
  *
  */
 
+//include <string.h>
 #include "ags/engine/ac/dynobj/cc_serializer.h"
-#include "ags/engine/ac/dynobj/all_dynamicclasses.h"
-#include "ags/engine/ac/dynobj/all_scriptclasses.h"
-#include "ags/engine/ac/dynobj/scriptcamera.h"
-#include "ags/engine/ac/dynobj/scriptcontainers.h"
-#include "ags/engine/ac/dynobj/scriptfile.h"
-#include "ags/engine/ac/dynobj/scriptuserobject.h"
-#include "ags/engine/ac/dynobj/scriptviewport.h"
+#include "ags/engine/ac/dynobj/all_dynamic_classes.h"
+#include "ags/engine/ac/dynobj/all_script_classes.h"
+#include "ags/engine/ac/dynobj/script_camera.h"
+#include "ags/engine/ac/dynobj/script_containers.h"
+#include "ags/engine/ac/dynobj/script_file.h"
+#include "ags/engine/ac/dynobj/script_user_object.h"
+#include "ags/engine/ac/dynobj/script_viewport.h"
 #include "ags/engine/ac/game.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/plugins/agsplugin.h"
-#include "ags/plugins/pluginobjectreader.h"
+#include "ags/plugins/ags_plugin.h"
+#include "ags/plugins/plugin_object_reader.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/dynobj/cc_serializer.h b/engines/ags/engine/ac/dynobj/cc_serializer.h
index ae6109f656..443e9b5500 100644
--- a/engines/ags/engine/ac/dynobj/cc_serializer.h
+++ b/engines/ags/engine/ac/dynobj/cc_serializer.h
@@ -20,15 +20,14 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_CCSERIALIZER_H
-#define AGS_ENGINE_AC_DYNOBJ_CCSERIALIZER_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_SERIALIZER_H
+#define AGS_ENGINE_AC_DYNOBJ_SERIALIZER_H
 
-#include "ags/engine/ac/dynobj/cc_dynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_dynamic_object.h"
 
 namespace AGS3 {
 
 struct AGSDeSerializer : ICCObjectReader {
-	virtual ~AGSDeSerializer() {}
 	void Unserialize(int index, const char *objectType, const char *serializedData, int dataSize) override;
 };
 
diff --git a/engines/ags/engine/ac/dynobj/managedobjectpool.cpp b/engines/ags/engine/ac/dynobj/managed_object_pool.cpp
similarity index 95%
rename from engines/ags/engine/ac/dynobj/managedobjectpool.cpp
rename to engines/ags/engine/ac/dynobj/managed_object_pool.cpp
index 63d161c904..5b49a0aea1 100644
--- a/engines/ags/engine/ac/dynobj/managedobjectpool.cpp
+++ b/engines/ags/engine/ac/dynobj/managed_object_pool.cpp
@@ -21,8 +21,8 @@
  */
 
 #include "ags/lib/std/vector.h"
-#include "ags/engine/ac/dynobj/managedobjectpool.h"
-#include "ags/engine/ac/dynobj/cc_dynamicarray.h" // _GP(globalDynamicArray), constants
+#include "ags/engine/ac/dynobj/managed_object_pool.h"
+#include "ags/engine/ac/dynobj/cc_dynamic_array.h" // globalDynamicArray, constants
 #include "ags/shared/debugging/out.h"
 #include "ags/shared/util/string_utils.h"               // fputstring, etc
 #include "ags/shared/script/cc_error.h"
@@ -34,24 +34,22 @@ namespace AGS3 {
 
 using namespace AGS::Shared;
 
-static const auto OBJECT_CACHE_MAGIC_NUMBER = 0xa30b;
-static const auto SERIALIZE_BUFFER_SIZE = 10240;
-static const auto GARBAGE_COLLECTION_INTERVAL = 1024;
-static const auto RESERVED_SIZE = 2048;
+const auto OBJECT_CACHE_MAGIC_NUMBER = 0xa30b;
+const auto SERIALIZE_BUFFER_SIZE = 10240;
+const auto GARBAGE_COLLECTION_INTERVAL = 1024;
+const auto RESERVED_SIZE = 2048;
 
 int ManagedObjectPool::Remove(ManagedObject &o, bool force) {
 	if (!o.isUsed()) {
-		return 1;    // already removed
-	}
+		return 1;
+	} // already removed
 
 	bool canBeRemovedFromPool = o.callback->Dispose(o.addr, force) != 0;
 	if (!(canBeRemovedFromPool || force)) {
 		return 0;
 	}
 
-#ifdef DEBUG_MANAGED_OBJECTS
-	auto handle = o.handle;
-#endif
+	//auto handle = o.handle;
 	available_ids.push(o.handle);
 
 	handleByAddress.erase(o.addr);
@@ -291,8 +289,7 @@ int ManagedObjectPool::ReadFromDisk(Stream *in, ICCObjectReader *reader) {
 	auto version = in->ReadInt32();
 
 	switch (version) {
-	case 1:
-	{
+	case 1: {
 		// IMPORTANT: numObjs is "nextHandleId", which is why we iterate from 1 to numObjs-1
 		int numObjs = in->ReadInt32();
 		for (int i = 1; i < numObjs; i++) {
@@ -314,8 +311,7 @@ int ManagedObjectPool::ReadFromDisk(Stream *in, ICCObjectReader *reader) {
 		}
 	}
 	break;
-	case 2:
-	{
+	case 2: {
 		// This is actually number of objects written.
 		int objectsSize = in->ReadInt32();
 		for (int i = 0; i < objectsSize; i++) {
@@ -382,4 +378,6 @@ ManagedObjectPool::ManagedObjectPool() : objectCreationCounter(0), nextHandle(1)
 	handleByAddress.reserve(RESERVED_SIZE);
 }
 
+ManagedObjectPool pool;
+
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/managedobjectpool.h b/engines/ags/engine/ac/dynobj/managed_object_pool.h
similarity index 82%
rename from engines/ags/engine/ac/dynobj/managedobjectpool.h
rename to engines/ags/engine/ac/dynobj/managed_object_pool.h
index a33b76fe73..32ef7a5ea4 100644
--- a/engines/ags/engine/ac/dynobj/managedobjectpool.h
+++ b/engines/ags/engine/ac/dynobj/managed_object_pool.h
@@ -20,17 +20,18 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_MANAGEDOBJECTPOOL_H
-#define AGS_ENGINE_AC_DYNOBJ_MANAGEDOBJECTPOOL_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_CC_MANAGED_OBJECT_POOL_H
+#define AGS_ENGINE_AC_DYNOBJ_CC_MANAGED_OBJECT_POOL_H
 
 #include "ags/lib/std/vector.h"
 #include "ags/lib/std/queue.h"
 #include "ags/lib/std/map.h"
-#include "ags/engine/script/runtimescriptvalue.h"
-#include "ags/engine/ac/dynobj/cc_dynamicobject.h"   // ICCDynamicObject
-#include "ags/shared/util/string_types.h"
+
+#include "ags/engine/script/runtime_script_value.h"
+#include "ags/engine/ac/dynobj/cc_dynamic_object.h"   // ICCDynamicObject
 
 namespace AGS3 {
+
 namespace AGS {
 namespace Shared {
 class Stream;
@@ -41,11 +42,11 @@ using namespace AGS; // FIXME later
 
 struct Pointer_Hash {
 	uint operator()(const char *v) const {
-		uint x = static_cast<uint>(reinterpret_cast<uintptr>(v));
-		return x + (x >> 3);
+		return static_cast<uint>(reinterpret_cast<uintptr>(v));
 	}
 };
 
+
 struct ManagedObjectPool final {
 private:
 	// TODO: find out if we can make handle size_t
@@ -62,11 +63,13 @@ private:
 			return obj_type != kScValUndefined;
 		}
 
-		ManagedObject()
-			: obj_type(kScValUndefined), handle(0), addr(nullptr), callback(nullptr), refCount(0) {
+		ManagedObject() : obj_type(kScValUndefined), handle(0), addr(nullptr),
+			callback(nullptr), refCount(0) {
 		}
-		ManagedObject(ScriptValueType obj_type_, int32_t handle_, const char *addr_, ICCDynamicObject *callback_)
-			: obj_type(obj_type_), handle(handle_), addr(addr_), callback(callback_), refCount(0) {
+		ManagedObject(ScriptValueType theType, int32_t theHandle,
+		              const char *theAddr, ICCDynamicObject *theCallback)
+			: obj_type(theType), handle(theHandle), addr(theAddr),
+			  callback(theCallback), refCount(0) {
 		}
 	};
 
diff --git a/engines/ags/engine/ac/dynobj/scriptaudiochannel.h b/engines/ags/engine/ac/dynobj/script_audio_channel.h
similarity index 91%
rename from engines/ags/engine/ac/dynobj/scriptaudiochannel.h
rename to engines/ags/engine/ac/dynobj/script_audio_channel.h
index 52cb3c7d53..b3cc119cb0 100644
--- a/engines/ags/engine/ac/dynobj/scriptaudiochannel.h
+++ b/engines/ags/engine/ac/dynobj/script_audio_channel.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTAUDIOCHANNEL_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTAUDIOCHANNEL_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptcamera.cpp b/engines/ags/engine/ac/dynobj/script_camera.cpp
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptcamera.cpp
rename to engines/ags/engine/ac/dynobj/script_camera.cpp
index ecfe1ae980..70a0b370a9 100644
--- a/engines/ags/engine/ac/dynobj/scriptcamera.cpp
+++ b/engines/ags/engine/ac/dynobj/script_camera.cpp
@@ -20,8 +20,8 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptcamera.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/dynobj/script_camera.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/shared/util/bbop.h"
 #include "ags/globals.h"
 
diff --git a/engines/ags/engine/ac/dynobj/scriptcamera.h b/engines/ags/engine/ac/dynobj/script_camera.h
similarity index 97%
rename from engines/ags/engine/ac/dynobj/scriptcamera.h
rename to engines/ags/engine/ac/dynobj/script_camera.h
index 8d77f9d205..a7de352497 100644
--- a/engines/ags/engine/ac/dynobj/scriptcamera.h
+++ b/engines/ags/engine/ac/dynobj/script_camera.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTCAMERA_H
 #define AGS_ENGINE_AC_DYNOBJ_SCRIPTCAMERA_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptcontainers.h b/engines/ags/engine/ac/dynobj/script_containers.h
similarity index 100%
rename from engines/ags/engine/ac/dynobj/scriptcontainers.h
rename to engines/ags/engine/ac/dynobj/script_containers.h
diff --git a/engines/ags/engine/ac/dynobj/scriptdatetime.cpp b/engines/ags/engine/ac/dynobj/script_date_time.cpp
similarity index 97%
rename from engines/ags/engine/ac/dynobj/scriptdatetime.cpp
rename to engines/ags/engine/ac/dynobj/script_date_time.cpp
index b055e380e1..4245bfd5b4 100644
--- a/engines/ags/engine/ac/dynobj/scriptdatetime.cpp
+++ b/engines/ags/engine/ac/dynobj/script_date_time.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptdatetime.h"
+#include "ags/engine/ac/dynobj/script_date_time.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptdatetime.h b/engines/ags/engine/ac/dynobj/script_date_time.h
similarity index 90%
rename from engines/ags/engine/ac/dynobj/scriptdatetime.h
rename to engines/ags/engine/ac/dynobj/script_date_time.h
index e7a002d504..9685cfc535 100644
--- a/engines/ags/engine/ac/dynobj/scriptdatetime.h
+++ b/engines/ags/engine/ac/dynobj/script_date_time.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDATETIME_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDATETIME_H
+#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_DATE_TIME_H
+#define AGS_ENGINE_DYNOBJ_SCRIPT_DATE_TIME_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptdialog.h b/engines/ags/engine/ac/dynobj/script_dialog.h
similarity index 92%
rename from engines/ags/engine/ac/dynobj/scriptdialog.h
rename to engines/ags/engine/ac/dynobj/script_dialog.h
index 92a5de4581..82f22c314d 100644
--- a/engines/ags/engine/ac/dynobj/scriptdialog.h
+++ b/engines/ags/engine/ac/dynobj/script_dialog.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDIALOG_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDIALOG_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTDIALOG_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTDIALOG_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.cpp b/engines/ags/engine/ac/dynobj/script_dialog_options_rendering.cpp
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.cpp
rename to engines/ags/engine/ac/dynobj/script_dialog_options_rendering.cpp
index d442b16e8f..af83ee0e3d 100644
--- a/engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.cpp
+++ b/engines/ags/engine/ac/dynobj/script_dialog_options_rendering.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptdialogoptionsrendering.h"
+#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.h b/engines/ags/engine/ac/dynobj/script_dialog_options_rendering.h
similarity index 90%
rename from engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.h
rename to engines/ags/engine/ac/dynobj/script_dialog_options_rendering.h
index 43d34d9f2c..b071194620 100644
--- a/engines/ags/engine/ac/dynobj/scriptdialogoptionsrendering.h
+++ b/engines/ags/engine/ac/dynobj/script_dialog_options_rendering.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDIALOGOPTIONSRENDERING_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDIALOGOPTIONSRENDERING_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_DIALOG_OPTIONS_RENDERING_H
+#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_DIALOG_OPTIONS_RENDERING_H
 
-#include "ags/engine/ac/dynobj/scriptdrawingsurface.h"
+#include "ags/engine/ac/dynobj/script_drawing_surface.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptdict.cpp b/engines/ags/engine/ac/dynobj/script_dict.cpp
similarity index 95%
rename from engines/ags/engine/ac/dynobj/scriptdict.cpp
rename to engines/ags/engine/ac/dynobj/script_dict.cpp
index 7991471e11..e874fbf8ce 100644
--- a/engines/ags/engine/ac/dynobj/scriptdict.cpp
+++ b/engines/ags/engine/ac/dynobj/script_dict.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptdict.h"
+#include "ags/engine/ac/dynobj/script_dict.h"
 
 namespace AGS3 {
 
@@ -36,7 +36,7 @@ const char *ScriptDictBase::GetType() {
 
 int ScriptDictBase::Serialize(const char *address, char *buffer, int bufsize) {
 	size_t total_sz = CalcSerializeSize() + sizeof(int32_t) * 2;
-	if (bufsize < 0 || total_sz >(size_t)bufsize) {
+	if (bufsize < 0 || total_sz > (size_t)bufsize) {
 		// buffer not big enough, ask for a bigger one
 		return -((int)total_sz);
 	}
diff --git a/engines/ags/engine/ac/dynobj/scriptdict.h b/engines/ags/engine/ac/dynobj/script_dict.h
similarity index 97%
rename from engines/ags/engine/ac/dynobj/scriptdict.h
rename to engines/ags/engine/ac/dynobj/script_dict.h
index 797e053cf1..5ac0146793 100644
--- a/engines/ags/engine/ac/dynobj/scriptdict.h
+++ b/engines/ags/engine/ac/dynobj/script_dict.h
@@ -37,7 +37,8 @@
 #define AGS_ENGINE_AC_DYNOBJ_SCRIPTDICT_H
 
 #include "ags/lib/std/map.h"
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/lib/std/map.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 #include "ags/shared/util/string.h"
 #include "ags/shared/util/string_types.h"
 
@@ -135,8 +136,7 @@ private:
 		_dic[elem_key] = elem_value;
 		return true;
 	}
-	void DeleteItem(ConstIterator it) {
-		/* do nothing */
+	void DeleteItem(ConstIterator it) { /* do nothing */
 	}
 
 	size_t CalcSerializeSize() override {
@@ -185,7 +185,6 @@ private:
 };
 
 typedef ScriptDictImpl< std::map<String, String>, true, true > ScriptDict;
-// TODO: Not sure if current std::map implement works for LessThan to give a key ordering
 typedef ScriptDictImpl< std::map<String, String, IgnoreCase_LessThan>, true, false > ScriptDictCI;
 typedef ScriptDictImpl< std::unordered_map<String, String>, false, true > ScriptHashDict;
 typedef ScriptDictImpl< std::unordered_map<String, String, IgnoreCase_Hash, IgnoreCase_EqualTo>, false, false > ScriptHashDictCI;
diff --git a/engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp b/engines/ags/engine/ac/dynobj/script_drawing_surface.cpp
similarity index 83%
rename from engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
rename to engines/ags/engine/ac/dynobj/script_drawing_surface.cpp
index ea3391b59c..f4cfa2b9cd 100644
--- a/engines/ags/engine/ac/dynobj/scriptdrawingsurface.cpp
+++ b/engines/ags/engine/ac/dynobj/script_drawing_surface.cpp
@@ -20,14 +20,14 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptdrawingsurface.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/engine/ac/dynobj/script_drawing_surface.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/ac/runtime_defines.h"
 #include "ags/shared/ac/common.h"
-#include "ags/engine/ac/drawingsurface.h"
-#include "ags/engine/ac/gamestate.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/engine/ac/drawing_surface.h"
+#include "ags/engine/ac/game_state.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/globals.h"
 
@@ -45,19 +45,17 @@ Bitmap *ScriptDrawingSurface::GetBitmapSurface() {
 		return _G(dynamicallyCreatedSurfaces)[dynamicSurfaceNumber];
 	else if (linkedBitmapOnly != nullptr)
 		return linkedBitmapOnly;
-	else if (roomMaskType > kRoomAreaNone)
-		return _GP(thisroom).GetMask(roomMaskType);
-	quit("!DrawingSurface: attempted to use surface after Release was called");
+	else
+		quit("!DrawingSurface: attempted to use surface after Release was called");
+
 	return nullptr;
 }
 
 Bitmap *ScriptDrawingSurface::StartDrawing() {
-	//abufBackup = abuf;
 	return this->GetBitmapSurface();
 }
 
 void ScriptDrawingSurface::FinishedDrawingReadOnly() {
-	//abuf = abufBackup;
 }
 
 void ScriptDrawingSurface::FinishedDrawing() {
@@ -79,7 +77,7 @@ const char *ScriptDrawingSurface::GetType() {
 
 int ScriptDrawingSurface::Serialize(const char *address, char *buffer, int bufsize) {
 	StartSerialize(buffer);
-	SerializeInt((roomBackgroundNumber & 0xFFFF) | (roomMaskType << 16));
+	SerializeInt(roomBackgroundNumber);
 	SerializeInt(dynamicSpriteNumber);
 	SerializeInt(dynamicSurfaceNumber);
 	SerializeInt(currentColour);
@@ -93,9 +91,7 @@ int ScriptDrawingSurface::Serialize(const char *address, char *buffer, int bufsi
 
 void ScriptDrawingSurface::Unserialize(int index, const char *serializedData, int dataSize) {
 	StartUnserialize(serializedData, dataSize);
-	int room_ds = UnserializeInt();
-	roomBackgroundNumber = static_cast<short>(room_ds & 0xFFFF);
-	roomMaskType = (RoomAreaMask)(room_ds >> 16);
+	roomBackgroundNumber = UnserializeInt();
 	dynamicSpriteNumber = UnserializeInt();
 	dynamicSurfaceNumber = UnserializeInt();
 	currentColour = UnserializeInt();
@@ -109,7 +105,6 @@ void ScriptDrawingSurface::Unserialize(int index, const char *serializedData, in
 
 ScriptDrawingSurface::ScriptDrawingSurface() {
 	roomBackgroundNumber = -1;
-	roomMaskType = kRoomAreaNone;
 	dynamicSpriteNumber = -1;
 	dynamicSurfaceNumber = -1;
 	isLinkedBitmapOnly = false;
diff --git a/engines/ags/engine/ac/dynobj/scriptdrawingsurface.h b/engines/ags/engine/ac/dynobj/script_drawing_surface.h
similarity index 84%
rename from engines/ags/engine/ac/dynobj/scriptdrawingsurface.h
rename to engines/ags/engine/ac/dynobj/script_drawing_surface.h
index 36385aa95a..0d0317095e 100644
--- a/engines/ags/engine/ac/dynobj/scriptdrawingsurface.h
+++ b/engines/ags/engine/ac/dynobj/script_drawing_surface.h
@@ -20,11 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDRAWINGSURFACE_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDRAWINGSURFACE_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_DRAWING_SURFACE_H
+#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_DRAWING_SURFACE_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
@@ -35,10 +34,7 @@ class Bitmap;
 } // namespace AGS
 
 struct ScriptDrawingSurface final : AGSCCDynamicObject {
-	// These numbers and types are used to determine the source of this drawing surface;
-	// only one of them can be valid for this surface.
 	int roomBackgroundNumber;
-	RoomAreaMask roomMaskType;
 	int dynamicSpriteNumber;
 	int dynamicSurfaceNumber;
 	bool isLinkedBitmapOnly;
diff --git a/engines/ags/engine/ac/dynobj/scriptdynamicsprite.cpp b/engines/ags/engine/ac/dynobj/script_dynamic_sprite.cpp
similarity index 94%
rename from engines/ags/engine/ac/dynobj/scriptdynamicsprite.cpp
rename to engines/ags/engine/ac/dynobj/script_dynamic_sprite.cpp
index d21f430d9b..e89034f87e 100644
--- a/engines/ags/engine/ac/dynobj/scriptdynamicsprite.cpp
+++ b/engines/ags/engine/ac/dynobj/script_dynamic_sprite.cpp
@@ -20,8 +20,8 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptdynamicsprite.h"
-#include "ags/engine/ac/dynamicsprite.h"
+#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
+#include "ags/engine/ac/dynamic_sprite.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptdynamicsprite.h b/engines/ags/engine/ac/dynobj/script_dynamic_sprite.h
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptdynamicsprite.h
rename to engines/ags/engine/ac/dynobj/script_dynamic_sprite.h
index 82bb60d7f3..6bdc82fca6 100644
--- a/engines/ags/engine/ac/dynobj/scriptdynamicsprite.h
+++ b/engines/ags/engine/ac/dynobj/script_dynamic_sprite.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDYNAMICSPRITE_H
 #define AGS_ENGINE_AC_DYNOBJ_SCRIPTDYNAMICSPRITE_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptfile.cpp b/engines/ags/engine/ac/dynobj/script_file.cpp
similarity index 98%
rename from engines/ags/engine/ac/dynobj/scriptfile.cpp
rename to engines/ags/engine/ac/dynobj/script_file.cpp
index 8798d2bb41..7ed5e22be9 100644
--- a/engines/ags/engine/ac/dynobj/scriptfile.cpp
+++ b/engines/ags/engine/ac/dynobj/script_file.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptfile.h"
+#include "ags/engine/ac/dynobj/script_file.h"
 #include "ags/engine/ac/global_file.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/dynobj/scriptfile.h b/engines/ags/engine/ac/dynobj/script_file.h
similarity index 93%
rename from engines/ags/engine/ac/dynobj/scriptfile.h
rename to engines/ags/engine/ac/dynobj/script_file.h
index 990223d0e6..46411fb406 100644
--- a/engines/ags/engine/ac/dynobj/scriptfile.h
+++ b/engines/ags/engine/ac/dynobj/script_file.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTFILE_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTFILE_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTFILE_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTFILE_H
 
-#include "ags/engine/ac/dynobj/cc_dynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_dynamic_object.h"
 #include "ags/shared/util/file.h"
 
 namespace AGS3 {
@@ -50,7 +50,6 @@ struct sc_File final : ICCDynamicObject {
 	void Close();
 
 	sc_File();
-	virtual ~sc_File() {}
 
 	// Legacy support for reading and writing object values by their relative offset
 	const char *GetFieldPtr(const char *address, intptr_t offset) override;
diff --git a/engines/ags/engine/ac/dynobj/scriptgui.h b/engines/ags/engine/ac/dynobj/script_gui.h
similarity index 92%
rename from engines/ags/engine/ac/dynobj/scriptgui.h
rename to engines/ags/engine/ac/dynobj/script_gui.h
index 8f9294d1c2..9ce397522c 100644
--- a/engines/ags/engine/ac/dynobj/scriptgui.h
+++ b/engines/ags/engine/ac/dynobj/script_gui.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTGUI_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTGUI_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTGUI_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTGUI_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scripthotspot.h b/engines/ags/engine/ac/dynobj/script_hotspot.h
similarity index 89%
rename from engines/ags/engine/ac/dynobj/scripthotspot.h
rename to engines/ags/engine/ac/dynobj/script_hotspot.h
index 43dfe5a465..e7f7074e89 100644
--- a/engines/ags/engine/ac/dynobj/scripthotspot.h
+++ b/engines/ags/engine/ac/dynobj/script_hotspot.h
@@ -20,14 +20,14 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTHOTSPOT_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTHOTSPOT_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTHOTSPOT_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTHOTSPOT_H
 
 namespace AGS3 {
 
 struct ScriptHotspot {
-	int id = 0;
-	int reserved = 0;
+	int id;
+	int reserved;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/scriptinvitem.h b/engines/ags/engine/ac/dynobj/script_inv_item.h
similarity index 89%
rename from engines/ags/engine/ac/dynobj/scriptinvitem.h
rename to engines/ags/engine/ac/dynobj/script_inv_item.h
index 5b2175f992..7bb3a1243d 100644
--- a/engines/ags/engine/ac/dynobj/scriptinvitem.h
+++ b/engines/ags/engine/ac/dynobj/script_inv_item.h
@@ -20,14 +20,14 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTINVITEM_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTINVITEM_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTINVITEM_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTINVITEM_H
 
 namespace AGS3 {
 
 struct ScriptInvItem {
-	int id = 0;
-	int reserved = 0;
+	int id;
+	int reserved;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/scriptmouse.h b/engines/ags/engine/ac/dynobj/script_mouse.h
similarity index 92%
rename from engines/ags/engine/ac/dynobj/scriptmouse.h
rename to engines/ags/engine/ac/dynobj/script_mouse.h
index d935dbdbb5..cbb38c8a0a 100644
--- a/engines/ags/engine/ac/dynobj/scriptmouse.h
+++ b/engines/ags/engine/ac/dynobj/script_mouse.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTMOUSE_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTMOUSE_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTMOUSE_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTMOUSE_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptobject.h b/engines/ags/engine/ac/dynobj/script_object.h
similarity index 84%
rename from engines/ags/engine/ac/dynobj/scriptobject.h
rename to engines/ags/engine/ac/dynobj/script_object.h
index 0cb519a6e8..09169551f5 100644
--- a/engines/ags/engine/ac/dynobj/scriptobject.h
+++ b/engines/ags/engine/ac/dynobj/script_object.h
@@ -20,19 +20,18 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTOBJECT_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTOBJECT_H
+#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_OBJECT_H
+#define AGS_ENGINE_DYNOBJ_SCRIPT_OBJECT_H
 
-#include "ags/engine/ac/roomobject.h"
+#include "ags/engine/ac/room_object.h"
 
 namespace AGS3 {
 
-// TODO: Check whether these should be made int32
 // 64 bit: Struct size must be 8 byte for scripts to work
 struct ScriptObject {
-	int id = 0;
+	int id;
 	//RoomObject *obj;
-	int __padding = 0;
+	int __padding;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/scriptoverlay.cpp b/engines/ags/engine/ac/dynobj/script_overlay.cpp
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptoverlay.cpp
rename to engines/ags/engine/ac/dynobj/script_overlay.cpp
index 673224f4de..443cb5f3d6 100644
--- a/engines/ags/engine/ac/dynobj/scriptoverlay.cpp
+++ b/engines/ags/engine/ac/dynobj/script_overlay.cpp
@@ -20,11 +20,11 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptoverlay.h"
+#include "ags/engine/ac/dynobj/script_overlay.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/runtime_defines.h"
-#include "ags/engine/ac/screenoverlay.h"
+#include "ags/engine/ac/screen_overlay.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/dynobj/scriptoverlay.h b/engines/ags/engine/ac/dynobj/script_overlay.h
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptoverlay.h
rename to engines/ags/engine/ac/dynobj/script_overlay.h
index df73fa8881..5d8faba3a8 100644
--- a/engines/ags/engine/ac/dynobj/scriptoverlay.h
+++ b/engines/ags/engine/ac/dynobj/script_overlay.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTOVERLAY_H
 #define AGS_ENGINE_AC_DYNOBJ_SCRIPTOVERLAY_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptregion.h b/engines/ags/engine/ac/dynobj/script_region.h
similarity index 89%
rename from engines/ags/engine/ac/dynobj/scriptregion.h
rename to engines/ags/engine/ac/dynobj/script_region.h
index dc25f96be5..bcb45c5572 100644
--- a/engines/ags/engine/ac/dynobj/scriptregion.h
+++ b/engines/ags/engine/ac/dynobj/script_region.h
@@ -20,14 +20,14 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTREGION_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTREGION_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTREGION_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTREGION_H
 
 namespace AGS3 {
 
 struct ScriptRegion {
-	int id = 0;
-	int reserved = 0;
+	int id;
+	int reserved;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/scriptset.cpp b/engines/ags/engine/ac/dynobj/script_set.cpp
similarity index 95%
rename from engines/ags/engine/ac/dynobj/scriptset.cpp
rename to engines/ags/engine/ac/dynobj/script_set.cpp
index 8141fc8913..b96b0df1f3 100644
--- a/engines/ags/engine/ac/dynobj/scriptset.cpp
+++ b/engines/ags/engine/ac/dynobj/script_set.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptset.h"
+#include "ags/engine/ac/dynobj/script_set.h"
 
 namespace AGS3 {
 
@@ -36,7 +36,7 @@ const char *ScriptSetBase::GetType() {
 
 int ScriptSetBase::Serialize(const char *address, char *buffer, int bufsize) {
 	size_t total_sz = CalcSerializeSize() + sizeof(int32_t) * 2;
-	if (bufsize < 0 || total_sz >(size_t)bufsize) {
+	if (bufsize < 0 || total_sz > (size_t)bufsize) {
 		// buffer not big enough, ask for a bigger one
 		return -((int)total_sz);
 	}
diff --git a/engines/ags/engine/ac/dynobj/scriptset.h b/engines/ags/engine/ac/dynobj/script_set.h
similarity index 97%
rename from engines/ags/engine/ac/dynobj/scriptset.h
rename to engines/ags/engine/ac/dynobj/script_set.h
index 1782f4f461..0ff0957e8e 100644
--- a/engines/ags/engine/ac/dynobj/scriptset.h
+++ b/engines/ags/engine/ac/dynobj/script_set.h
@@ -37,8 +37,7 @@
 
 #include "ags/lib/std/set.h"
 #include "ags/lib/std/unordered_set.h"
-#include "ags/lib/std/map.h"
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 #include "ags/shared/util/string.h"
 #include "ags/shared/util/string_types.h"
 
@@ -115,8 +114,7 @@ private:
 	bool TryAddItem(const char *item, size_t len) {
 		return _set.insert(String(item, len))._value;
 	}
-	void DeleteItem(ConstIterator it) {
-		/* do nothing */
+	void DeleteItem(ConstIterator it) { /* do nothing */
 	}
 
 	size_t CalcSerializeSize() override {
diff --git a/engines/ags/engine/ac/dynobj/scriptstring.cpp b/engines/ags/engine/ac/dynobj/script_string.cpp
similarity index 97%
rename from engines/ags/engine/ac/dynobj/scriptstring.cpp
rename to engines/ags/engine/ac/dynobj/script_string.cpp
index b9bafcd446..cb3b0d3eeb 100644
--- a/engines/ags/engine/ac/dynobj/scriptstring.cpp
+++ b/engines/ags/engine/ac/dynobj/script_string.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptstring.h"
+#include "ags/engine/ac/dynobj/script_string.h"
 #include "ags/engine/ac/string.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/dynobj/scriptstring.h b/engines/ags/engine/ac/dynobj/script_string.h
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptstring.h
rename to engines/ags/engine/ac/dynobj/script_string.h
index 200eb93b24..29b56b9bf8 100644
--- a/engines/ags/engine/ac/dynobj/scriptstring.h
+++ b/engines/ags/engine/ac/dynobj/script_string.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTSTRING_H
 #define AGS_ENGINE_AC_DYNOBJ_SCRIPTSTRING_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptsystem.h b/engines/ags/engine/ac/dynobj/script_system.h
similarity index 93%
rename from engines/ags/engine/ac/dynobj/scriptsystem.h
rename to engines/ags/engine/ac/dynobj/script_system.h
index 47b30c4d23..e2aac0c903 100644
--- a/engines/ags/engine/ac/dynobj/scriptsystem.h
+++ b/engines/ags/engine/ac/dynobj/script_system.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTSYSTEM_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTSYSTEM_H
+#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_SYSTEM_H
+#define AGS_ENGINE_DYNOBJ_SCRIPT_SYSTEM_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptuserobject.cpp b/engines/ags/engine/ac/dynobj/script_user_object.cpp
similarity index 98%
rename from engines/ags/engine/ac/dynobj/scriptuserobject.cpp
rename to engines/ags/engine/ac/dynobj/script_user_object.cpp
index 81a7095405..313e095e84 100644
--- a/engines/ags/engine/ac/dynobj/scriptuserobject.cpp
+++ b/engines/ags/engine/ac/dynobj/script_user_object.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "ags/lib/std/memory.h"
-#include "ags/engine/ac/dynobj/scriptuserobject.h"
+#include "ags/engine/ac/dynobj/script_user_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptuserobject.h b/engines/ags/engine/ac/dynobj/script_user_object.h
similarity index 95%
rename from engines/ags/engine/ac/dynobj/scriptuserobject.h
rename to engines/ags/engine/ac/dynobj/script_user_object.h
index 44ae8bf68c..c7a3433e2d 100644
--- a/engines/ags/engine/ac/dynobj/scriptuserobject.h
+++ b/engines/ags/engine/ac/dynobj/script_user_object.h
@@ -26,10 +26,10 @@
 //
 //=============================================================================
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTUSERSTRUCT_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTUSERSTRUCT_H
+#ifndef AGS_ENGINE_DYNOBJ__SCRIPTUSERSTRUCT_H
+#define AGS_ENGINE_DYNOBJ__SCRIPTUSERSTRUCT_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
@@ -79,10 +79,8 @@ private:
 
 // Helper functions for setting up custom managed structs based on ScriptUserObject.
 namespace ScriptStructHelpers {
-
 // Creates a managed Point object, represented as a pair of X and Y coordinates.
 ScriptUserObject *CreatePoint(int x, int y);
-
 } // namespace ScriptStructHelpers
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/scriptviewframe.cpp b/engines/ags/engine/ac/dynobj/script_view_frame.cpp
similarity index 97%
rename from engines/ags/engine/ac/dynobj/scriptviewframe.cpp
rename to engines/ags/engine/ac/dynobj/script_view_frame.cpp
index 44e2d7271c..112441621d 100644
--- a/engines/ags/engine/ac/dynobj/scriptviewframe.cpp
+++ b/engines/ags/engine/ac/dynobj/script_view_frame.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptviewframe.h"
+#include "ags/engine/ac/dynobj/script_view_frame.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptviewframe.h b/engines/ags/engine/ac/dynobj/script_view_frame.h
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptviewframe.h
rename to engines/ags/engine/ac/dynobj/script_view_frame.h
index 29edce6559..b0c4e9b014 100644
--- a/engines/ags/engine/ac/dynobj/scriptviewframe.h
+++ b/engines/ags/engine/ac/dynobj/script_view_frame.h
@@ -23,7 +23,7 @@
 #ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTVIEWFRAME_H
 #define AGS_ENGINE_AC_DYNOBJ_SCRIPTVIEWFRAME_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/dynobj/scriptviewport.cpp b/engines/ags/engine/ac/dynobj/script_viewport.cpp
similarity index 96%
rename from engines/ags/engine/ac/dynobj/scriptviewport.cpp
rename to engines/ags/engine/ac/dynobj/script_viewport.cpp
index f1802a7042..cee7cf140b 100644
--- a/engines/ags/engine/ac/dynobj/scriptviewport.cpp
+++ b/engines/ags/engine/ac/dynobj/script_viewport.cpp
@@ -20,8 +20,8 @@
  *
  */
 
-#include "ags/engine/ac/dynobj/scriptviewport.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/dynobj/script_viewport.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/shared/util/bbop.h"
 #include "ags/globals.h"
 
diff --git a/engines/ags/engine/ac/dynobj/scriptviewport.h b/engines/ags/engine/ac/dynobj/script_viewport.h
similarity index 92%
rename from engines/ags/engine/ac/dynobj/scriptviewport.h
rename to engines/ags/engine/ac/dynobj/script_viewport.h
index fc4ea1a258..8d0a06f581 100644
--- a/engines/ags/engine/ac/dynobj/scriptviewport.h
+++ b/engines/ags/engine/ac/dynobj/script_viewport.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTVIEWPORT_H
-#define AGS_ENGINE_AC_DYNOBJ_SCRIPTVIEWPORT_H
+#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_VIEWPORT_H
+#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_VIEWPORT_H
 
-#include "ags/engine/ac/dynobj/cc_agsdynamicobject.h"
+#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index 3972398dea..20fe42887c 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -23,22 +23,22 @@
 #include "ags/engine/ac/event.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/global_room.h"
 #include "ags/engine/ac/global_screen.h"
 #include "ags/engine/ac/gui.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/ac/screen.h"
 #include "ags/shared/script/cc_error.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
-#include "ags/plugins/agsplugin.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
+#include "ags/plugins/ags_plugin.h"
 #include "ags/plugins/plugin_engine.h"
 #include "ags/engine/script/script.h"
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/engine/gfx/ddb.h"
-#include "ags/engine/gfx/graphicsdriver.h"
+#include "ags/engine/gfx/graphics_driver.h"
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/engine/ac/timer.h"
 #include "ags/globals.h"
@@ -60,8 +60,6 @@ int run_claimable_event(const char *tsname, bool includeRoom, int numParams, con
 
 	if (includeRoom && _G(roominst)) {
 		toret = RunScriptFunctionIfExists(_G(roominst), tsname, numParams, params);
-		if (_G(abort_engine))
-			return -1;
 
 		if (_G(eventClaimed) == EVENT_CLAIMED) {
 			_G(eventClaimed) = eventClaimedOldValue;
@@ -99,12 +97,12 @@ void run_room_event(int id) {
 	}
 }
 
-void run_event_block_inv(int invNum, int event_) {
+void run_event_block_inv(int invNum, int event) {
 	_G(evblockbasename) = "inventory%d";
 	if (_G(loaded_game_file_version) > kGameVersion_272) {
-		run_interaction_script(_GP(game).invScripts[invNum].get(), event_);
+		run_interaction_script(_GP(game).invScripts[invNum].get(), event);
 	} else {
-		run_interaction_event(_GP(game).intrInv[invNum].get(), event_);
+		run_interaction_event(_GP(game).intrInv[invNum].get(), event);
 	}
 
 }
@@ -180,9 +178,6 @@ void process_event(EventHappened *evp) {
 		} else
 			quit("process_event: RunEvBlock: unknown evb type");
 
-		if (_G(abort_engine))
-			return;
-
 		_G(evblockbasename) = oldbasename;
 		_G(evblocknum) = oldblocknum;
 
@@ -210,7 +205,7 @@ void process_event(EventHappened *evp) {
 
 		const bool ignore_transition = (_GP(play).screen_tint > 0);
 		if (((theTransition == FADE_CROSSFADE) || (theTransition == FADE_DISSOLVE)) &&
-			(_G(saved_viewport_bitmap) == nullptr) && !ignore_transition) {
+		        (_G(saved_viewport_bitmap) == nullptr) && !ignore_transition) {
 			// transition type was not crossfade/dissolve when the screen faded out,
 			// but it is now when the screen fades in (Eg. a save game was restored
 			// with a different setting). Therefore just fade normally.
@@ -219,7 +214,6 @@ void process_event(EventHappened *evp) {
 		}
 
 		// TODO: use normal coordinates instead of "native_size" and multiply_up_*?
-		//const Size &data_res = _GP(game).GetDataRes();
 		const Rect &viewport = _GP(play).GetMainViewport();
 
 		if ((theTransition == FADE_INSTANT) || ignore_transition)
@@ -255,7 +249,7 @@ void process_event(EventHappened *evp) {
 					int lyp = viewport.GetHeight() / 2 - boxhit / 2;
 					_G(gfxDriver)->Vsync();
 					temp_scr->Blit(saved_backbuf, lxp, lyp, lxp, lyp,
-						boxwid, boxhit);
+					               boxwid, boxhit);
 					render_to_screen();
 					WaitForNextFrame();
 				}
@@ -287,7 +281,6 @@ void process_event(EventHappened *evp) {
 				WaitForNextFrame();
 				transparency -= 16;
 			}
-			_G(saved_viewport_bitmap)->Release();
 
 			delete _G(saved_viewport_bitmap);
 			_G(saved_viewport_bitmap) = nullptr;
@@ -296,7 +289,7 @@ void process_event(EventHappened *evp) {
 		} else if (theTransition == FADE_DISSOLVE) {
 			int pattern[16] = { 0, 4, 14, 9, 5, 11, 2, 8, 10, 3, 12, 7, 15, 6, 13, 1 };
 			int aa, bb, cc;
-			color interpal[256];
+			RGB interpal[256];
 
 			IDriverDependantBitmap *ddb = prepare_screen_for_transition_in();
 			for (aa = 0; aa < 16; aa++) {
@@ -360,9 +353,10 @@ void processallevents(int numev, EventHappened *evlist) {
 	_G(inside_processevent)++;
 
 	for (dd = 0; dd < numev; dd++) {
+
 		process_event(&copyOfList[dd]);
 
-		if (room_was != _GP(play).room_changes || _G(abort_engine))
+		if (room_was != _GP(play).room_changes)
 			break;  // changed room, so discard other events
 	}
 
diff --git a/engines/ags/engine/ac/event.h b/engines/ags/engine/ac/event.h
index eeb041c1df..72a219b813 100644
--- a/engines/ags/engine/ac/event.h
+++ b/engines/ags/engine/ac/event.h
@@ -24,7 +24,7 @@
 #define AGS_ENGINE_AC_EVENT_H
 
 #include "ags/engine/ac/runtime_defines.h"
-#include "ags/engine/script/runtimescriptvalue.h"
+#include "ags/engine/script/runtime_script_value.h"
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index 6c651de28b..cab74dad94 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -21,12 +21,12 @@
  */
 
 #include "ags/engine/ac/asset_helper.h"
-#include "ags/shared/ac/audiocliptype.h"
+#include "ags/shared/ac/audio_clip_type.h"
 #include "ags/engine/ac/file.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/game.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/global_file.h"
 #include "ags/engine/ac/path_helper.h"
 #include "ags/engine/ac/runtime_defines.h"
@@ -34,10 +34,9 @@
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/engine/debugging/debugger.h"
 #include "ags/shared/util/misc.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/shared/util/stream.h"
-#include "ags/shared/util/filestream.h"
-#include "ags/shared/core/assetmanager.h"
+#include "ags/shared/core/asset_manager.h"
 #include "ags/shared/core/asset.h"
 #include "ags/engine/main/engine.h"
 #include "ags/engine/main/game_file.h"
@@ -48,11 +47,8 @@
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
-#include "ags/engine/ac/dynobj/scriptstring.h"
+#include "ags/engine/ac/dynobj/script_string.h"
 #include "ags/globals.h"
-#include "ags/ags.h"
-#include "common/config-manager.h"
-#include "common/debug.h"
 
 namespace AGS3 {
 
@@ -75,10 +71,10 @@ int File_Delete(const char *fnmm) {
 	if (!ResolveScriptPath(fnmm, false, rp))
 		return 0;
 
-	if (File::DeleteFile(rp.FullPath))
+	if (::remove(rp.FullPath) == 0)
 		return 1;
 	if (_G(errnum) == AL_ENOENT && !rp.AltPath.IsEmpty() && rp.AltPath.Compare(rp.FullPath) != 0)
-		return File::DeleteFile(rp.AltPath) ? 1 : 0;
+		return ::remove(rp.AltPath) == 0 ? 1 : 0;
 	return 0;
 }
 
@@ -204,10 +200,11 @@ int File_GetPosition(sc_File *fil) {
 //=============================================================================
 
 
-const char *GameInstallRootToken = "$INSTALLDIR$";
-const char *UserSavedgamesRootToken = "$MYDOCS$";
-const char *GameSavedgamesDirToken = "$SAVEGAMEDIR$";
-const char *GameDataDirToken = "$APPDATADIR$";
+const String GameInstallRootToken = "$INSTALLDIR$";
+const String UserSavedgamesRootToken = "$MYDOCS$";
+const String GameSavedgamesDirToken = "$SAVEGAMEDIR$";
+const String GameDataDirToken = "$APPDATADIR$";
+const String UserConfigFileToken = "$CONFIGFILE$";
 
 void FixupFilename(char *filename) {
 	const char *illegal = _G(platform)->GetIllegalFileChars();
@@ -222,14 +219,20 @@ void FixupFilename(char *filename) {
 	}
 }
 
+String PathFromInstallDir(const String &path) {
+	if (Path::IsRelativePath(path))
+		return Path::ConcatPaths(_GP(ResPaths).DataDir, path);
+	return path;
+}
+
 // Tests if there is a special path token in the beginning of the given path;
 // if there is and there is no slash between token and the rest of the string,
 // then assigns new string that has such slash.
 // Returns TRUE if the new string was created, and FALSE if the path was good.
 bool FixSlashAfterToken(const String &path, const String &token, String &new_path) {
 	if (path.CompareLeft(token) == 0 && path.GetLength() > token.GetLength() &&
-		path[token.GetLength()] != '/') {
-		new_path = String::FromFormat("%s/%s", token.GetCStr(), path.Mid(token.GetLength()).GetCStr());
+	        path[token.GetLength()] != '/') {
+		new_path = Path::ConcatPaths(token, path.Mid(token.GetLength()));
 		return true;
 	}
 	return false;
@@ -239,33 +242,78 @@ String FixSlashAfterToken(const String &path) {
 	String fixed_path = path;
 	Path::FixupPath(fixed_path);
 	if (FixSlashAfterToken(fixed_path, GameInstallRootToken, fixed_path) ||
-		FixSlashAfterToken(fixed_path, UserSavedgamesRootToken, fixed_path) ||
-		FixSlashAfterToken(fixed_path, GameSavedgamesDirToken, fixed_path) ||
-		FixSlashAfterToken(fixed_path, GameDataDirToken, fixed_path))
+	        FixSlashAfterToken(fixed_path, UserSavedgamesRootToken, fixed_path) ||
+	        FixSlashAfterToken(fixed_path, GameSavedgamesDirToken, fixed_path) ||
+	        FixSlashAfterToken(fixed_path, GameDataDirToken, fixed_path))
 		return fixed_path;
 	return path;
 }
 
-String MakeSpecialSubDir(const String &sp_dir) {
-	if (is_relative_filename(sp_dir))
-		return sp_dir;
-	String full_path = sp_dir;
-	if (full_path.GetLast() != '/' && full_path.GetLast() != '\\')
-		full_path.AppendChar('/');
-	full_path.Append(_GP(game).saveGameFolderName);
-	Directory::CreateDirectory(full_path);
-	return full_path;
+String PreparePathForWriting(const FSLocation &fsloc, const String &filename) {
+	if (Directory::CreateAllDirectories(fsloc.BaseDir, fsloc.FullDir))
+		return Path::ConcatPaths(fsloc.FullDir, filename);
+	return "";
 }
 
-String MakeAppDataPath() {
-	return "./";
+FSLocation GetGlobalUserConfigDir() {
+	String dir = _G(platform)->GetUserGlobalConfigDirectory();
+	if (Path::IsRelativePath(dir)) // relative dir is resolved relative to the game data dir
+		return FSLocation(_GP(ResPaths).DataDir, Path::ConcatPaths(_GP(ResPaths).DataDir, dir));
+	return FSLocation(dir, dir);
+}
+
+FSLocation GetGameUserConfigDir() {
+	String dir = _G(platform)->GetUserConfigDirectory();
+	if (Path::IsRelativePath(dir)) // relative dir is resolved relative to the game data dir
+		return FSLocation(_GP(ResPaths).DataDir, Path::ConcatPaths(_GP(ResPaths).DataDir, dir));
+	else if (_GP(usetup).local_user_conf) // directive to use game dir location
+		return FSLocation(_GP(ResPaths).DataDir);
+	// For absolute dir, we assume it's a special directory prepared for AGS engine
+	// and therefore amend it with a game own subdir
+	return FSLocation(dir, Path::ConcatPaths(dir, _GP(game).saveGameFolderName));
+}
+
+// A helper function that deduces a data directory either using default system location,
+// or user option from config. In case of a default location a path is appended with
+// game's "save folder" name, which is meant to separate files from different games.
+static FSLocation MakeGameDataDir(const String &default_dir, const String &user_option) {
+	if (user_option.IsEmpty()) {
+		String dir = default_dir;
+		if (Path::IsRelativePath(dir)) // relative dir is resolved relative to the game data dir
+			return FSLocation(_GP(ResPaths).DataDir, Path::ConcatPaths(_GP(ResPaths).DataDir, dir));
+		// For absolute dir, we assume it's a special directory prepared for AGS engine
+		// and therefore amend it with a game own subdir
+		return FSLocation(dir, Path::ConcatPaths(dir, _GP(game).saveGameFolderName));
+	}
+	// If this location is set up by user config, then use it as is (resolving relative path if necessary)
+	String dir = user_option;
+	if (Path::IsSameOrSubDir(_GP(ResPaths).DataDir, dir)) // check if it's inside game dir
+		return FSLocation(_GP(ResPaths).DataDir, Path::MakeRelativePath(_GP(ResPaths).DataDir, dir));
+	dir = Path::MakeAbsolutePath(dir);
+	return FSLocation(dir, dir);
+}
+
+FSLocation GetGameAppDataDir() {
+	return MakeGameDataDir(_G(platform)->GetAllUsersDataDirectory(), _GP(usetup).shared_data_dir);
+}
+
+FSLocation GetGameUserDataDir() {
+	return MakeGameDataDir(_G(platform)->GetUserSavedgamesDirectory(), _GP(usetup).user_data_dir);
 }
 
 bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath &rp) {
-	debugC(::AGS::kDebugFilePath, "ResolveScriptPath(%s)", orig_sc_path.GetCStr());
 	rp = ResolvedPath();
 
-	bool is_absolute = !is_relative_filename(orig_sc_path);
+	// File tokens (they must be the only thing in script path)
+	if (orig_sc_path.Compare(UserConfigFileToken) == 0) {
+		auto loc = GetGameUserConfigDir();
+		rp.FullPath = Path::ConcatPaths(loc.FullDir, DefaultConfigFileName);
+		rp.BaseDir = loc.BaseDir;
+		return true;
+	}
+
+	// Test absolute paths
+	bool is_absolute = !Path::IsRelativePath(orig_sc_path);
 	if (is_absolute && !read_only) {
 		debug_script_warn("Attempt to access file '%s' denied (cannot write to absolute path)", orig_sc_path.GetCStr());
 		return false;
@@ -273,108 +321,65 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 
 	if (is_absolute) {
 		rp.FullPath = orig_sc_path;
-		debugC(::AGS::kDebugFilePath, "Full path detected");
 		return true;
 	}
-	/*
-	if (read_only) {
-		// For reading files, first try as a save file, then fall back
-		// in the game folder. This handles cases where some games like
-		// The Blackwell Legacy write to files in the game folder
-		rp.BaseDir = SAVE_FOLDER_PREFIX;
-		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
-			orig_sc_path.GetNullableCStr());
-		rp.AltPath = orig_sc_path;
-	} else {
-		// For writing files, always use as save files
-		rp.BaseDir = SAVE_FOLDER_PREFIX;
-		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
-			orig_sc_path.GetNullableCStr());
-	}
-	*/
+
+	// Resolve location tokens
 	String sc_path = FixSlashAfterToken(orig_sc_path);
-	String parent_dir;
+	FSLocation parent_dir;
 	String child_path;
 	String alt_path;
-	if (sc_path.CompareLeft(GameInstallRootToken) == 0) {
+	if (sc_path.CompareLeft(GameInstallRootToken, GameInstallRootToken.GetLength()) == 0) {
 		if (!read_only) {
 			debug_script_warn("Attempt to access file '%s' denied (cannot write to game installation directory)",
-				sc_path.GetCStr());
+			                  sc_path.GetCStr());
 			return false;
 		}
-		parent_dir = get_install_dir();
-		parent_dir.AppendChar('/');
-		child_path = sc_path.Mid(strlen(GameInstallRootToken));
-	} else if (sc_path.CompareLeft(GameSavedgamesDirToken) == 0) {
-		parent_dir = get_save_game_directory();
-		child_path = sc_path.Mid(strlen(GameSavedgamesDirToken));
-#if AGS_PLATFORM_SCUMMVM
-		// Remap "agsgame.*"
-		const char  *agsSavePrefix = "/agssave.";
-		if (child_path.CompareLeft(agsSavePrefix) == 0) {
-			debugC(::AGS::kDebugFilePath, "Remapping agssave.* to ScummVM savegame files");
-			String suffix = child_path.Mid(strlen(agsSavePrefix));
-			if (suffix.CompareLeft("*") == 0) {
-				Common::String file_name = ::AGS::g_vm->getSaveStateName(999);
-				Common::replace(file_name, "999", "*");
-				child_path = file_name;
-			} else {
-				int slotNum = suffix.ToInt();
-				child_path = ::AGS::g_vm->getSaveStateName(slotNum);
-			}
-		}
-#endif
-	} else if (sc_path.CompareLeft(GameDataDirToken) == 0) {
-		parent_dir = MakeAppDataPath();
-		child_path = sc_path.Mid(strlen(GameDataDirToken));
+		parent_dir = FSLocation(_GP(ResPaths).DataDir);
+		child_path = sc_path.Mid(GameInstallRootToken.GetLength());
+	} else if (sc_path.CompareLeft(GameSavedgamesDirToken, GameSavedgamesDirToken.GetLength()) == 0) {
+		parent_dir = FSLocation(get_save_game_directory()); // FIXME: get FSLocation of save dir
+		child_path = sc_path.Mid(GameSavedgamesDirToken.GetLength());
+	} else if (sc_path.CompareLeft(GameDataDirToken, GameDataDirToken.GetLength()) == 0) {
+		parent_dir = GetGameAppDataDir();
+		child_path = sc_path.Mid(GameDataDirToken.GetLength());
 	} else {
 		child_path = sc_path;
 
-		// For cases where a file is trying to write to a game path, always remap
-		// it to write to a savefile. For normal reading, we thus need to give
-		// preference to any save file with a given name before looking in the
-		// game folder. This for example fixes an issue with The Blackwell Legacy,
-		// which wants to create a new prog.bwl in the game folder
-		parent_dir = SAVE_FOLDER_PREFIX;
-
-		if (read_only) {
-			alt_path = String::FromFormat("%s/%s", get_install_dir().GetCStr(),
-				sc_path.GetCStr());
+		// For games which were made without having safe paths in mind,
+		// provide two paths: a path to the local directory and a path to
+		// AppData directory.
+		// This is done in case game writes a file by local path, and would
+		// like to read it back later. Since AppData path has higher priority,
+		// game will first check the AppData location and find a previously
+		// written file.
+		// If no file was written yet, but game is trying to read a pre-created
+		// file in the installation directory, then such file will be found
+		// following the 'alt_path'.
+		parent_dir = GetGameAppDataDir();
+		// Set alternate non-remapped "unsafe" path for read-only operations
+		if (read_only)
+			alt_path = Path::ConcatPaths(_GP(ResPaths).DataDir, sc_path);
+
+		// For games made in the safe-path-aware versions of AGS, report a warning
+		// if the unsafe path is used for write operation
+		if (!read_only && _GP(game).options[OPT_SAFEFILEPATHS]) {
+			debug_script_warn("Attempt to access file '%s' denied (cannot write to game installation directory);\nPath will be remapped to the app data directory: '%s'",
+			                  sc_path.GetCStr(), parent_dir.FullDir.GetCStr());
 		}
 	}
 
-	// Sometimes we have multiple consecutive slashes or backslashes.
-	// Remove all of them at the start of the child path.
-	while (!child_path.IsEmpty() && (child_path[0u] == '\\' || child_path[0u] == '/'))
-		child_path.ClipLeft(1);
-
-#if AGS_PLATFORM_SCUMMVM
-	// For files on savepath, always ensure it starts with the game target prefix to avoid
-	// conflicts (as we usually have the same save dir for all games).
-	if (parent_dir == SAVE_FOLDER_PREFIX) {
-		debugC(::AGS::kDebugFilePath, "Adding ScummVM game target prefix");
-		String gameTarget = ConfMan.getActiveDomainName();
-		if (child_path.CompareLeft(gameTarget) != 0)
-			child_path = String::FromFormat("%s-%s", gameTarget.GetCStr(), child_path.GetCStr());
-	}
-#endif
-
-	String full_path = String::FromFormat("%s%s", parent_dir.GetCStr(), child_path.GetCStr());
+	String full_path = Path::ConcatPaths(parent_dir.FullDir, child_path);
 	// don't allow write operations for relative paths outside game dir
 	if (!read_only) {
-		if (!Path::IsSameOrSubDir(parent_dir, full_path)) {
+		if (!Path::IsSameOrSubDir(parent_dir.FullDir, full_path)) {
 			debug_script_warn("Attempt to access file '%s' denied (outside of game directory)", sc_path.GetCStr());
 			return false;
 		}
 	}
-	rp.BaseDir = parent_dir;
+	rp.BaseDir = parent_dir.BaseDir;
 	rp.FullPath = full_path;
 	rp.AltPath = alt_path;
-
-	debugC(::AGS::kDebugFilePath, "Resolved path: %s", full_path.GetCStr());
-	if (!alt_path.IsEmpty())
-		debugC(::AGS::kDebugFilePath, "Alternative path: %s", alt_path.GetCStr());
-
 	return true;
 }
 
@@ -389,20 +394,11 @@ bool ResolveWritePathAndCreateDirs(const String &sc_path, ResolvedPath &rp) {
 }
 
 Stream *LocateAsset(const AssetPath &path, size_t &asset_size) {
-	String assetlib = path.first;
-	String assetname = path.second;
-	bool needsetback = false;
-	// Change to the different library, if required
-	// TODO: teaching AssetManager to register multiple libraries simultaneously
-	// will let us skip this step, and also make this operation much faster.
-	if (!assetlib.IsEmpty() && assetlib.CompareNoCase(_GP(ResPaths).GamePak.Name) != 0) {
-		AssetManager::SetDataFile(get_known_assetlib(assetlib));
-		needsetback = true;
-	}
-	Stream *asset_stream = AssetManager::OpenAsset(assetname);
-	asset_size = AssetManager::GetLastAssetSize();
-	if (needsetback)
-		AssetManager::SetDataFile(_GP(ResPaths).GamePak.Path);
+	String assetname = path.Name;
+	String filter = path.Filter;
+	soff_t asset_sz = 0;
+	Stream *asset_stream = _GP(AssetMgr)->OpenAsset(assetname, filter, &asset_sz);
+	asset_size = asset_sz;
 	return asset_stream;
 }
 
@@ -483,112 +479,31 @@ PACKFILE *PackfileFromAsset(const AssetPath &path, size_t &asset_size) {
 	return nullptr;
 }
 
-bool DoesAssetExistInLib(const AssetPath &assetname) {
-	bool needsetback = false;
-	// Change to the different library, if required
-	// TODO: teaching AssetManager to register multiple libraries simultaneously
-	// will let us skip this step, and also make this operation much faster.
-	if (!assetname.first.IsEmpty() && assetname.first.CompareNoCase(_GP(ResPaths).GamePak.Name) != 0) {
-		AssetManager::SetDataFile(get_known_assetlib(assetname.first));
-		needsetback = true;
-	}
-	bool res = AssetManager::DoesAssetExist(assetname.second);
-	if (needsetback)
-		AssetManager::SetDataFile(_GP(ResPaths).GamePak.Path);
-	return res;
-}
-
-void set_install_dir(const String &path, const String &audio_path, const String &voice_path) {
-	if (path.IsEmpty())
-		_G(installDirectory) = ".";
-	else
-		_G(installDirectory) = Path::MakePathNoSlash(path);
-	if (audio_path.IsEmpty())
-		_G(installAudioDirectory) = ".";
-	else
-		_G(installAudioDirectory) = Path::MakePathNoSlash(audio_path);
-	if (voice_path.IsEmpty())
-		_G(installVoiceDirectory) = ".";
-	else
-		_G(installVoiceDirectory) = Path::MakePathNoSlash(voice_path);
-}
-
-String get_install_dir() {
-	return _G(installDirectory);
-}
-
-String get_audio_install_dir() {
-	return _G(installAudioDirectory);
-}
-
-String get_voice_install_dir() {
-	return _G(installVoiceDirectory);
-}
-
-void get_install_dir_path(char *buffer, const char *fileName) {
-	sprintf(buffer, "%s/%s", _G(installDirectory).GetCStr(), fileName);
+bool DoesAssetExistInLib(const AssetPath &path) {
+	String assetname = path.Name;
+	String filter = path.Filter;
+	return _GP(AssetMgr)->DoesAssetExist(assetname, filter);
 }
 
 String find_assetlib(const String &filename) {
 	String libname = cbuf_to_string_and_free(ci_find_file(_GP(ResPaths).DataDir, filename));
 	if (AssetManager::IsDataFile(libname))
 		return libname;
-	if (Path::ComparePaths(_GP(ResPaths).DataDir, _G(installDirectory)) != 0) {
+	if (Path::ComparePaths(_GP(ResPaths).DataDir, _GP(ResPaths).DataDir2) != 0) {
 		// Hack for running in Debugger
-		libname = cbuf_to_string_and_free(ci_find_file(_G(installDirectory), filename));
+		libname = cbuf_to_string_and_free(ci_find_file(_GP(ResPaths).DataDir2, filename));
 		if (AssetManager::IsDataFile(libname))
 			return libname;
 	}
 	return "";
 }
 
-// Looks up for known valid asset library and returns path, or empty string if failed
-String get_known_assetlib(const String &filename) {
-	// TODO: write now there's only 3 regular PAKs, so we may do this quick
-	// string comparison, but if we support more maybe we could use a table.
-	if (filename.CompareNoCase(_GP(ResPaths).GamePak.Name) == 0)
-		return _GP(ResPaths).GamePak.Path;
-	if (filename.CompareNoCase(_GP(ResPaths).AudioPak.Name) == 0)
-		return _GP(ResPaths).AudioPak.Path;
-	if (filename.CompareNoCase(_GP(ResPaths).SpeechPak.Name) == 0)
-		return _GP(ResPaths).SpeechPak.Path;
-	return String();
-}
-
-Stream *find_open_asset(const String &filename) {
-	Stream *asset_s = Shared::AssetManager::OpenAsset(filename);
-	if (!asset_s && Path::ComparePaths(_GP(ResPaths).DataDir, _G(installDirectory)) != 0) {
-		// Just in case they're running in Debug, try standalone file in compiled folder
-		asset_s = ci_fopen(String::FromFormat("%s/%s", _G(installDirectory).GetCStr(), filename.GetCStr()));
-	}
-	return asset_s;
-}
-
 AssetPath get_audio_clip_assetpath(int bundling_type, const String &filename) {
-	// Special case is explicitly defined audio directory, which should be
-	// tried first regardless of bundling type.
-	if (Path::ComparePaths(_GP(ResPaths).DataDir, _G(installAudioDirectory)) != 0) {
-		String filepath = String::FromFormat("%s/%s", _G(installAudioDirectory).GetCStr(), filename.GetCStr());
-		if (Path::IsFile(filepath))
-			return AssetPath("", filepath);
-	}
-
-	if (bundling_type == AUCL_BUNDLE_EXE)
-		return AssetPath(_GP(ResPaths).GamePak.Name, filename);
-	else if (bundling_type == AUCL_BUNDLE_VOX)
-		return AssetPath(_GP(game).GetAudioVOXName(), filename);
-	return AssetPath();
+	return AssetPath(filename, "audio");
 }
 
 AssetPath get_voice_over_assetpath(const String &filename) {
-	// Special case is explicitly defined voice-over directory, which should be
-	// tried first.
-	if (Path::ComparePaths(_GP(ResPaths).DataDir, _G(installVoiceDirectory)) != 0) {
-		String filepath = String::FromFormat("%s/%s", _G(installVoiceDirectory).GetCStr(), filename.GetCStr());
-		if (Path::IsFile(filepath))
-			return AssetPath("", filepath);
-	}
-	return AssetPath(_GP(ResPaths).SpeechPak.Name, filename);
+	return AssetPath(filename, "voice");
 }
 
 ScriptFileHandle valid_handles[MAX_OPEN_SCRIPT_FILES + 1];
@@ -634,8 +549,6 @@ Stream *get_valid_file_stream_from_handle(int32_t handle, const char *operation_
 //
 //=============================================================================
 
-
-
 // int (const char *fnmm)
 RuntimeScriptValue Sc_File_Delete(const RuntimeScriptValue *params, int32_t param_count) {
 	API_SCALL_INT_POBJ(File_Delete, const char);
diff --git a/engines/ags/engine/ac/file.h b/engines/ags/engine/ac/file.h
index fb116d1213..ed0f0f01c9 100644
--- a/engines/ags/engine/ac/file.h
+++ b/engines/ags/engine/ac/file.h
@@ -29,7 +29,7 @@
 #ifndef AGS_ENGINE_AC_FILE_H
 #define AGS_ENGINE_AC_FILE_H
 
-#include "ags/engine/ac/dynobj/scriptfile.h"
+#include "ags/engine/ac/dynobj/script_file.h"
 #include "ags/engine/ac/runtime_defines.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index d0100b7715..1c0e3abef2 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -23,20 +23,17 @@
 #include "ags/engine/ac/game.h"
 #include "ags/shared/ac/common.h"
 #include "ags/shared/ac/view.h"
-#include "ags/shared/ac/audiocliptype.h"
-#include "ags/engine/ac/audiochannel.h"
+#include "ags/engine/ac/audio_channel.h"
 #include "ags/engine/ac/character.h"
-#include "ags/engine/ac/charactercache.h"
-#include "ags/engine/ac/characterextras.h"
-#include "ags/shared/ac/dialogtopic.h"
+#include "ags/engine/ac/character_cache.h"
+#include "ags/shared/ac/dialog_topic.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/engine/ac/dynamicsprite.h"
+#include "ags/engine/ac/dynamic_sprite.h"
 #include "ags/engine/ac/event.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_audio.h"
-#include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_display.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/global_gui.h"
@@ -44,65 +41,45 @@
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/gui.h"
 #include "ags/engine/ac/hotspot.h"
-#include "ags/engine/ac/lipsync.h"
+#include "ags/shared/ac/keycode.h"
+#include "ags/engine/ac/lip_sync.h"
 #include "ags/engine/ac/mouse.h"
-#include "ags/engine/ac/movelist.h"
-#include "ags/engine/ac/objectcache.h"
+#include "ags/engine/ac/object_cache.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/path_helper.h"
 #include "ags/engine/ac/sys_events.h"
-#include "ags/engine/ac/region.h"
-#include "ags/engine/ac/richgamemedia.h"
-#include "ags/engine/ac/room.h"
-#include "ags/engine/ac/roomobject.h"
-#include "ags/engine/ac/roomstatus.h"
-#include "ags/engine/ac/runtime_defines.h"
-#include "ags/engine/ac/screenoverlay.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/engine/ac/rich_game_media.h"
+#include "ags/engine/ac/room_status.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/ac/string.h"
-#include "ags/engine/ac/system.h"
-#include "ags/engine/ac/timer.h"
 #include "ags/engine/ac/translation.h"
-#include "ags/engine/ac/dynobj/all_dynamicclasses.h"
-#include "ags/engine/ac/dynobj/all_scriptclasses.h"
-#include "ags/engine/ac/dynobj/cc_audiochannel.h"
-#include "ags/engine/ac/dynobj/cc_audioclip.h"
-#include "ags/engine/ac/dynobj/scriptcamera.h"
+#include "ags/engine/ac/dynobj/all_dynamic_classes.h"
+#include "ags/engine/ac/dynobj/all_script_classes.h"
+#include "ags/engine/ac/dynobj/script_camera.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/engine/debugging/debugger.h"
 #include "ags/shared/debugging/out.h"
-#include "ags/engine/device/mousew32.h"
+#include "ags/engine/device/mouse_w32.h"
 #include "ags/shared/font/fonts.h"
 #include "ags/engine/game/savegame.h"
-#include "ags/engine/game/savegame_components.h"
-#include "ags/engine/game/savegame_internal.h"
-#include "ags/engine/gui/animatingguibutton.h"
 #include "ags/shared/gfx/bitmap.h"
-#include "ags/engine/gfx/graphicsdriver.h"
-#include "ags/engine/gfx/gfxfilter.h"
-#include "ags/engine/gui/guidialog.h"
+#include "ags/engine/gfx/graphics_driver.h"
+#include "ags/shared/gui/gui_button.h"
+#include "ags/engine/gui/gui_dialog.h"
 #include "ags/engine/main/engine.h"
-#include "ags/engine/main/graphics_mode.h"
-#include "ags/engine/main/main.h"
 #include "ags/engine/media/audio/audio_system.h"
-#include "ags/plugins/agsplugin.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
+#include "ags/engine/platform/base/sys_main.h"
 #include "ags/plugins/plugin_engine.h"
-#include "ags/shared/script/cc_error.h"
-#include "ags/engine/script/runtimescriptvalue.h"
 #include "ags/engine/script/script.h"
 #include "ags/engine/script/script_runtime.h"
-#include "ags/shared/util/alignedstream.h"
 #include "ags/shared/util/directory.h"
-#include "ags/shared/util/filestream.h" // TODO: needed only because plugins expect file handle
+#include "ags/shared/util/file.h"
 #include "ags/shared/util/path.h"
-#include "ags/shared/util/string_utils.h"
-#include "ags/engine/ac/keycode.h"
+
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
 #include "ags/globals.h"
-#include "ags/ags.h"
-#include "common/memstream.h"
 
 namespace AGS3 {
 
@@ -115,7 +92,7 @@ using namespace AGS::Engine;
 
 void Game_StopAudio(int audioType) {
 	if (((audioType < 0) || ((size_t)audioType >= _GP(game).audioClipTypes.size())) && (audioType != SCR_NO_VALUE))
-		quitprintf("!game.StopAudio: invalid audio type %d", audioType);
+		quitprintf("!Game.StopAudio: invalid audio type %d", audioType);
 	int aa;
 
 	for (aa = 0; aa < MAX_SOUND_CHANNELS; aa++) {
@@ -133,7 +110,7 @@ void Game_StopAudio(int audioType) {
 
 int Game_IsAudioPlaying(int audioType) {
 	if (((audioType < 0) || ((size_t)audioType >= _GP(game).audioClipTypes.size())) && (audioType != SCR_NO_VALUE))
-		quitprintf("!game.IsAudioPlaying: invalid audio type %d", audioType);
+		quitprintf("!Game.IsAudioPlaying: invalid audio type %d", audioType);
 
 	if (_GP(play).fast_forward)
 		return 0;
@@ -151,20 +128,20 @@ int Game_IsAudioPlaying(int audioType) {
 
 void Game_SetAudioTypeSpeechVolumeDrop(int audioType, int volumeDrop) {
 	if ((audioType < 0) || ((size_t)audioType >= _GP(game).audioClipTypes.size()))
-		quitprintf("!game.SetAudioTypeVolume: invalid audio type: %d", audioType);
+		quitprintf("!Game.SetAudioTypeVolume: invalid audio type: %d", audioType);
 
-	Debug::Printf("game.SetAudioTypeSpeechVolumeDrop: type: %d, drop: %d", audioType, volumeDrop);
+	Debug::Printf("Game.SetAudioTypeSpeechVolumeDrop: type: %d, drop: %d", audioType, volumeDrop);
 	_GP(game).audioClipTypes[audioType].volume_reduction_while_speech_playing = volumeDrop;
 	update_volume_drop_if_voiceover();
 }
 
 void Game_SetAudioTypeVolume(int audioType, int volume, int changeType) {
 	if ((volume < 0) || (volume > 100))
-		quitprintf("!game.SetAudioTypeVolume: volume %d is not between 0..100", volume);
+		quitprintf("!Game.SetAudioTypeVolume: volume %d is not between 0..100", volume);
 	if ((audioType < 0) || ((size_t)audioType >= _GP(game).audioClipTypes.size()))
-		quitprintf("!game.SetAudioTypeVolume: invalid audio type: %d", audioType);
+		quitprintf("!Game.SetAudioTypeVolume: invalid audio type: %d", audioType);
 
-	Debug::Printf("game.SetAudioTypeVolume: type: %d, volume: %d, change: %d", audioType, volume, changeType);
+	Debug::Printf("Game.SetAudioTypeVolume: type: %d, volume: %d, change: %d", audioType, volume, changeType);
 	if ((changeType == VOL_CHANGEEXISTING) ||
 	        (changeType == VOL_BOTH)) {
 		AudioChannelsLock lock;
@@ -223,7 +200,6 @@ void setup_for_dialog() {
 	_G(oldmouse) = _G(cur_cursor);
 	set_mouse_cursor(CURS_ARROW);
 }
-
 void restore_after_dialog() {
 	set_mouse_cursor(_G(oldmouse));
 	if (!_GP(play).mouse_cursor_hidden)
@@ -232,6 +208,7 @@ void restore_after_dialog() {
 }
 
 
+
 String get_save_game_directory() {
 	return _G(saveGameDirectory);
 }
@@ -244,52 +221,44 @@ void set_save_game_suffix(const String &suffix) {
 	_G(saveGameSuffix) = suffix;
 }
 
+String get_save_game_filename(int slotNum) {
+	return String::FromFormat("agssave.%03d%s", slotNum, _G(saveGameSuffix).GetCStr());
+}
+
 String get_save_game_path(int slotNum) {
-#if AGS_PLATFORM_SCUMMVM
-	return Common::String::format("%s%s", SAVE_FOLDER_PREFIX,
-		::AGS::g_vm->getSaveStateName(slotNum).c_str());
-#else
-	String filename;
-	filename.Format(sgnametemplate, slotNum);
-	String path = _G(_G(saveGameDirectory));
-	path.Append(filename);
-	path.Append(_G(saveGameSuffix));
-	return path;
-#endif
+	return Path::ConcatPaths(_G(saveGameDirectory), get_save_game_filename(slotNum));
 }
 
 // Convert a path possibly containing path tags into acceptable save path
 bool MakeSaveGameDir(const String &newFolder, ResolvedPath &rp) {
 	rp = ResolvedPath();
 	// don't allow absolute paths
-	if (!is_relative_filename(newFolder))
+	if (!Path::IsRelativePath(newFolder))
 		return false;
 
 	String base_dir;
 	String newSaveGameDir = FixSlashAfterToken(newFolder);
 
-	if (newSaveGameDir.CompareLeft(UserSavedgamesRootToken, strlen(UserSavedgamesRootToken)) == 0) {
+	if (newSaveGameDir.CompareLeft(UserSavedgamesRootToken, UserSavedgamesRootToken.GetLength()) == 0) {
 		if (_G(saveGameParent).IsEmpty()) {
-			base_dir = PathOrCurDir(_G(platform)->GetUserSavedgamesDirectory());
-			newSaveGameDir.ReplaceMid(0, strlen(UserSavedgamesRootToken), base_dir);
+			base_dir = PathFromInstallDir(_G(platform)->GetUserSavedgamesDirectory());
+			newSaveGameDir.ReplaceMid(0, UserSavedgamesRootToken.GetLength(), base_dir);
 		} else {
 			// If there is a custom save parent directory, then replace
 			// not only root token, but also first subdirectory
-			newSaveGameDir.ClipSection('/', 0, 1);
-			if (!newSaveGameDir.IsEmpty())
-				newSaveGameDir.PrependChar('/');
-			newSaveGameDir.Prepend(_G(saveGameParent));
+			newSaveGameDir.ClipSection('/', 0, 1); // TODO: Path helper function for this?
+			newSaveGameDir = Path::ConcatPaths(_G(saveGameParent), newSaveGameDir);
 			base_dir = _G(saveGameParent);
 		}
 	} else {
 		// Convert the path relative to installation folder into path relative to the
 		// safe save path with default name
 		if (_G(saveGameParent).IsEmpty()) {
-			base_dir = PathOrCurDir(_G(platform)->GetUserSavedgamesDirectory());
-			newSaveGameDir.Format("%s/%s/%s", base_dir.GetCStr(), _GP(game).saveGameFolderName, newFolder.GetCStr());
+			base_dir = PathFromInstallDir(_G(platform)->GetUserSavedgamesDirectory());
+			newSaveGameDir = Path::ConcatPaths(Path::ConcatPaths(base_dir, _GP(game).saveGameFolderName), newFolder);
 		} else {
 			base_dir = _G(saveGameParent);
-			newSaveGameDir.Format("%s/%s", _G(saveGameParent).GetCStr(), newFolder.GetCStr());
+			newSaveGameDir = Path::ConcatPaths(_G(saveGameParent), newFolder);
 		}
 		// For games made in the safe-path-aware versions of AGS, report a warning
 		if (_GP(game).options[OPT_SAFEFILEPATHS]) {
@@ -297,8 +266,8 @@ bool MakeSaveGameDir(const String &newFolder, ResolvedPath &rp) {
 			                  newFolder.GetCStr(), newSaveGameDir.GetCStr());
 		}
 	}
-	rp.BaseDir = Path::MakeTrailingSlash(base_dir);
-	rp.FullPath = Path::MakeTrailingSlash(newSaveGameDir);
+	rp.BaseDir = base_dir;
+	rp.FullPath = newSaveGameDir;
 	return true;
 }
 
@@ -311,14 +280,11 @@ bool SetCustomSaveParent(const String &path) {
 }
 
 bool SetSaveGameDirectoryPath(const char *newFolder, bool explicit_path) {
-#if AGS_PLATFORM_SCUMMVM
-	return false;
-#else
 	if (!newFolder || newFolder[0] == 0)
 		newFolder = ".";
 	String newSaveGameDir;
 	if (explicit_path) {
-		newSaveGameDir = Path::MakeTrailingSlash(newFolder);
+		newSaveGameDir = PathFromInstallDir(newFolder);
 		if (!Directory::CreateDirectory(newSaveGameDir))
 			return false;
 	} else {
@@ -332,29 +298,28 @@ bool SetSaveGameDirectoryPath(const char *newFolder, bool explicit_path) {
 		newSaveGameDir = rp.FullPath;
 	}
 
-	String newFolderTempFile = String::FromFormat("%s""agstmp.tmp", newSaveGameDir.GetCStr());
-	if (!Shared::File::TestCreateFile(newFolderTempFile))
+	String newFolderTempFile = Path::ConcatPaths(newSaveGameDir, "agstmp.tmp");
+	if (!File::TestCreateFile(newFolderTempFile))
 		return false;
 
 	// copy the Restart Game file, if applicable
-	String restartGamePath = String::FromFormat("%s""agssave.%d%s", _G(_G(saveGameDirectory)).GetCStr(), RESTART_POINT_SAVE_GAME_NUMBER, _G(saveGameSuffix).GetCStr());
-	Stream *restartGameFile = Shared::File::OpenFileRead(restartGamePath);
+	String restartGamePath = Path::ConcatPaths(_G(saveGameDirectory), get_save_game_filename(RESTART_POINT_SAVE_GAME_NUMBER));
+	Stream *restartGameFile = File::OpenFileRead(restartGamePath);
 	if (restartGameFile != nullptr) {
 		long fileSize = restartGameFile->GetLength();
 		char *mbuffer = (char *)malloc(fileSize);
 		restartGameFile->Read(mbuffer, fileSize);
 		delete restartGameFile;
 
-		restartGamePath.Format("%s""agssave.%d%s", newSaveGameDir.GetCStr(), RESTART_POINT_SAVE_GAME_NUMBER, _G(saveGameSuffix).GetCStr());
-		restartGameFile = Shared::File::CreateFile(restartGamePath);
+		restartGamePath = Path::ConcatPaths(newSaveGameDir, get_save_game_filename(RESTART_POINT_SAVE_GAME_NUMBER));
+		restartGameFile = File::CreateFile(restartGamePath);
 		restartGameFile->Write(mbuffer, fileSize);
 		delete restartGameFile;
 		free(mbuffer);
 	}
 
-	_G(_G(saveGameDirectory)) = newSaveGameDir;
+	_G(saveGameDirectory) = newSaveGameDir;
 	return true;
-#endif
 }
 
 int Game_SetSaveGameDirectory(const char *newFolder) {
@@ -372,7 +337,7 @@ const char *Game_GetSaveSlotDescription(int slnum) {
 
 void restore_game_dialog() {
 	can_run_delayed_command();
-	if (_GP(thisroom).Options.SaveLoadDisabled) {
+	if (_GP(thisroom).Options.SaveLoadDisabled == 1) {
 		DisplayMessage(983);
 		return;
 	}
@@ -450,6 +415,7 @@ void unload_game_file() {
 		delete _GP(moduleInst)[i];
 		_GP(scriptModules)[i].reset();
 	}
+
 	_GP(moduleInstFork).resize(0);
 	_GP(moduleInst).resize(0);
 	_GP(scriptModules).resize(0);
@@ -500,12 +466,12 @@ void unload_game_file() {
 	_GP(guis).clear();
 	free(_G(scrGui));
 
+	free_all_fonts();
+
 	pl_stop_plugins();
 	ccRemoveAllSymbols();
 	ccUnregisterAllObjects();
 
-	free_all_fonts();
-
 	free_do_once_tokens();
 	free(_GP(play).gui_draw_order);
 
@@ -515,13 +481,19 @@ void unload_game_file() {
 	_GP(game).Free();
 }
 
+
+
+
+
+
 const char *Game_GetGlobalStrings(int index) {
 	if ((index < 0) || (index >= MAXGLOBALSTRINGS))
-		quit("!game.GlobalStrings: invalid index");
+		quit("!Game.GlobalStrings: invalid index");
 
 	return CreateNewScriptString(_GP(play).globalstrings[index]);
 }
 
+
 // ** GetGameParameter replacement functions
 
 int Game_GetInventoryItemCount() {
@@ -627,7 +599,7 @@ int Game_GetTextReadingSpeed() {
 
 void Game_SetTextReadingSpeed(int newTextSpeed) {
 	if (newTextSpeed < 1)
-		quitprintf("!_GP(game).TextReadingSpeed: %d is an invalid speed", newTextSpeed);
+		quitprintf("!Game.TextReadingSpeed: %d is an invalid speed", newTextSpeed);
 
 	_GP(play).text_speed = newTextSpeed;
 }
@@ -659,7 +631,7 @@ const char *Game_GetName() {
 void Game_SetName(const char *newName) {
 	strncpy(_GP(play).game_name, newName, 99);
 	_GP(play).game_name[99] = 0;
-	::AGS::g_vm->set_window_title(_GP(play).game_name);
+	sys_window_set_title(_GP(play).game_name);
 }
 
 int Game_GetSkippingCutscene() {
@@ -729,21 +701,16 @@ const char *Game_GetTranslationFilename() {
 int Game_ChangeTranslation(const char *newFilename) {
 	if ((newFilename == nullptr) || (newFilename[0] == 0)) {
 		close_translation();
-		strcpy(_G(transFileName), "");
 		_GP(usetup).translation = "";
 		return 1;
 	}
 
-	String oldTransFileName;
-	oldTransFileName = _G(transFileName);
-
-	if (init_translation(newFilename, oldTransFileName.LeftSection('.'), false)) {
+	String oldTransFileName = get_translation_name();
+	if (init_translation(newFilename, oldTransFileName, false)) {
 		_GP(usetup).translation = newFilename;
 		return 1;
-	} else {
-		strcpy(_G(transFileName), oldTransFileName);
-		return 0;
 	}
+	return 0;
 }
 
 ScriptAudioClip *Game_GetAudioClip(int index) {
@@ -764,12 +731,8 @@ ScriptCamera *Game_GetAnyCamera(int index) {
 	return _GP(play).GetScriptCamera(index);
 }
 
-void Game_SimulateKeyPress(int key_) {
-	int platformKey = GetKeyForKeyPressCb(key_);
-	platformKey = PlatformKeyFromAgsKey(platformKey);
-	if (platformKey >= 0) {
-		simulate_keypress(platformKey);
-	}
+void Game_SimulateKeyPress(int key) {
+	ags_simulate_keypress(static_cast<eAGSKeyCode>(key));
 }
 
 //=============================================================================
@@ -802,7 +765,7 @@ void serialize_bitmap(const Shared::Bitmap *thispic, Stream *out) {
 	}
 }
 
-// On Windows we could just use IIDFromString but this is platform-independant
+// On Windows we could just use IIDFromString but this is _G(platform)-independant
 void convert_guid_from_text_to_binary(const char *guidText, unsigned char *buffer) {
 	guidText++; // skip {
 	for (int bytesDone = 0; bytesDone < 16; bytesDone++) {
@@ -813,8 +776,8 @@ void convert_guid_from_text_to_binary(const char *guidText, unsigned char *buffe
 		tempString[0] = guidText[0];
 		tempString[1] = guidText[1];
 		tempString[2] = 0;
-		int thisByte = 0;
-		sscanf(tempString, "%X", (unsigned int *)&thisByte);
+		uint thisByte = 0;
+		sscanf(tempString, "%X", &thisByte);
 
 		buffer[bytesDone] = thisByte;
 		guidText += 2;
@@ -873,55 +836,45 @@ void skip_serialized_bitmap(Stream *in) {
 }
 
 long write_screen_shot_for_vista(Stream *out, Bitmap *screenshot) {
-	// Save the screenshot to a memory stream so we can access the raw data
-	Common::MemoryWriteStreamDynamic bitmap(DisposeAfterUse::YES);
-	screenshot->SaveToFile(bitmap, _G(palette));
+	long fileSize = 0;
+	String tempFileName = String::FromFormat("%s""_tmpscht.bmp", _G(saveGameDirectory).GetCStr());
+
+	screenshot->SaveToFile(tempFileName, _G(palette));
 
 	update_polled_stuff_if_runtime();
 
-	// Write the bitmap to the output stream
-	out->Write(bitmap.getData(), bitmap.size());
+	if (Path::IsFile(tempFileName)) {
+		fileSize = File::GetFileSize(tempFileName);
+		char *buffer = (char *)malloc(fileSize);
 
-	return bitmap.size();
-}
+		Stream *temp_in = Shared::File::OpenFileRead(tempFileName);
+		temp_in->Read(buffer, fileSize);
+		delete temp_in;
+		::remove(tempFileName);
 
-void WriteGameSetupStructBase_Aligned(Stream *out) {
-	AlignedStream align_s(out, Shared::kAligned_Write);
-	_GP(game).GameSetupStructBase::WriteToFile(&align_s);
+		out->Write(buffer, fileSize);
+		free(buffer);
+	}
+	return fileSize;
 }
 
-#define MAGICNUMBER 0xbeefcafe
-
-void create_savegame_screenshot(Bitmap *&screenShot) {
-	// WORKAROUND: AGS originally only creates savegames if the game flags
-	// that it supports it. But we want it all the time for ScummVM GMM
-	if (/*_GP(game).options[OPT_SAVESCREENSHOT] */true) {
-		// Render the view without any UI elements
-		int old_flags = _G(debug_flags);
-		_G(debug_flags) |= DBG_NOIFACE;
-		construct_game_scene(true);
+Bitmap *create_savegame_screenshot() {
+	int usewid = data_to_game_coord(_GP(play).screenshot_width);
+	int usehit = data_to_game_coord(_GP(play).screenshot_height);
+	const Rect &viewport = _GP(play).GetMainViewport();
+	if (usewid > viewport.GetWidth())
+		usewid = viewport.GetWidth();
+	if (usehit > viewport.GetHeight())
+		usehit = viewport.GetHeight();
 
-		int usewid = data_to_game_coord(_GP(play).screenshot_width);
-		int usehit = data_to_game_coord(_GP(play).screenshot_height);
-		const Rect &viewport = _GP(play).GetMainViewport();
-		if (usewid > viewport.GetWidth())
-			usewid = viewport.GetWidth();
-		if (usehit > viewport.GetHeight())
-			usehit = viewport.GetHeight();
+	if ((_GP(play).screenshot_width < 16) || (_GP(play).screenshot_height < 16))
+		quit("!Invalid _GP(game).screenshot_width/height, must be from 16x16 to screen res");
 
-		if ((_GP(play).screenshot_width < 16) || (_GP(play).screenshot_height < 16))
-			quit("!Invalid game.screenshot_width/height, must be from 16x16 to screen res");
-
-		screenShot = CopyScreenIntoBitmap(usewid, usehit);
-		screenShot->GetAllegroBitmap()->makeOpaque();
-
-		// Restore original screen
-		_G(debug_flags) = old_flags;
-		construct_game_scene(true);
-	}
+	return CopyScreenIntoBitmap(usewid, usehit);
 }
 
 void save_game(int slotn, const char *descript) {
+
 	// dont allow save in rep_exec_always, because we dont save
 	// the state of blocked scripts
 	can_run_delayed_command();
@@ -932,488 +885,53 @@ void save_game(int slotn, const char *descript) {
 	}
 
 	if (_G(platform)->GetDiskFreeSpaceMB() < 2) {
-		Display("ERROR: There is not enough disk space free to save the game. Clear some disk space and try again.");
+		Display("ERROR: There is not enough disk space free to save the _GP(game). Clear some disk space and try again.");
 		return;
 	}
 
 	VALIDATE_STRING(descript);
-	String nametouse;
-	nametouse = get_save_game_path(slotn);
-
-	Bitmap *screenShot = nullptr;
-
-	// Screenshot
-	create_savegame_screenshot(screenShot);
-
-	Shared::PStream out = StartSavegame(nametouse, descript, screenShot);
-	if (out == nullptr)
-		quit("save_game: unable to open savegame file for writing");
+	String nametouse = get_save_game_path(slotn);
+	UBitmap screenShot;
+	if (_GP(game).options[OPT_SAVESCREENSHOT] != 0)
+		screenShot.reset(create_savegame_screenshot());
+
+	Engine::UStream out(StartSavegame(nametouse, descript, screenShot.get()));
+	if (out == nullptr) {
+		Display("ERROR: Unable to open savegame file for writing!");
+		return;
+	}
 
 	update_polled_stuff_if_runtime();
 
 	// Actual dynamic game data is saved here
-	SaveGameState(out);
+	SaveGameState(out.get());
 
 	if (screenShot != nullptr) {
 		int screenShotOffset = out->GetPosition() - sizeof(RICH_GAME_MEDIA_HEADER);
-		int screenShotSize = write_screen_shot_for_vista(out.get(), screenShot);
+		int screenShotSize = write_screen_shot_for_vista(out.get(), screenShot.get());
 
 		update_polled_stuff_if_runtime();
 
+		out.reset(Shared::File::OpenFile(nametouse, Shared::kFile_Open, Shared::kFile_ReadWrite));
 		out->Seek(12, kSeekBegin);
 		out->WriteInt32(screenShotOffset);
 		out->Seek(4);
 		out->WriteInt32(screenShotSize);
-
-		delete screenShot;
-	}
-}
-
-HSaveError restore_game_head_dynamic_values(Stream *in, RestoredData &r_data) {
-	r_data.FPS = in->ReadInt32();
-	r_data.CursorMode = in->ReadInt32();
-	r_data.CursorID = in->ReadInt32();
-	SavegameComponents::ReadLegacyCameraState(in, r_data);
-	set_loop_counter(in->ReadInt32());
-	return HSaveError::None();
-}
-
-void restore_game_spriteset(Stream *in) {
-	// ensure the sprite set is at least as large as it was
-	// when the game was saved
-	_GP(spriteset).EnlargeTo(in->ReadInt32() - 1); // they saved top_index + 1
-	// get serialized dynamic sprites
-	int sprnum = in->ReadInt32();
-	while (sprnum) {
-		unsigned char spriteflag = in->ReadByte();
-		add_dynamic_sprite(sprnum, read_serialized_bitmap(in));
-		_GP(game).SpriteInfos[sprnum].Flags = spriteflag;
-		sprnum = in->ReadInt32();
-	}
-}
-
-HSaveError restore_game_scripts(Stream *in, const PreservedParams &pp, RestoredData &r_data) {
-	// read the global script data segment
-	int gdatasize = in->ReadInt32();
-	if (pp.GlScDataSize != gdatasize) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching size of global script data.");
-	}
-	r_data.GlobalScript.Len = gdatasize;
-	r_data.GlobalScript.Data.reset(new char[gdatasize]);
-	in->Read(r_data.GlobalScript.Data.get(), gdatasize);
-
-	if (in->ReadInt32() != _G(numScriptModules)) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of script modules.");
-	}
-	r_data.ScriptModules.resize(_G(numScriptModules));
-	for (int i = 0; i < _G(numScriptModules); ++i) {
-		size_t module_size = in->ReadInt32();
-		if (pp.ScMdDataSize[i] != (int)module_size) {
-			return new SavegameError(kSvgErr_GameContentAssertion, String::FromFormat("Mismatching size of script module data, module %d.", i));
-		}
-		r_data.ScriptModules[i].Len = module_size;
-		r_data.ScriptModules[i].Data.reset(new char[module_size]);
-		in->Read(r_data.ScriptModules[i].Data.get(), module_size);
-	}
-	return HSaveError::None();
-}
-
-void ReadRoomStatus_Aligned(RoomStatus *roomstat, Stream *in) {
-	AlignedStream align_s(in, Shared::kAligned_Read);
-	roomstat->ReadFromFile_v321(&align_s);
-}
-
-void restore_game_room_state(Stream *in) {
-	int vv;
-
-	_G(displayed_room) = in->ReadInt32();
-
-	// read the room state for all the rooms the player has been in
-	RoomStatus *roomstat;
-	int beenhere;
-	for (vv = 0; vv < MAX_ROOMS; vv++) {
-		beenhere = in->ReadByte();
-		if (beenhere) {
-			roomstat = getRoomStatus(vv);
-			roomstat->beenhere = beenhere;
-
-			if (roomstat->beenhere) {
-				ReadRoomStatus_Aligned(roomstat, in);
-				if (roomstat->tsdatasize > 0) {
-					roomstat->tsdata = (char *)malloc(roomstat->tsdatasize + 8); // JJS: Why allocate 8 additional bytes?
-					in->Read(&roomstat->tsdata[0], roomstat->tsdatasize);
-				}
-			}
-		}
-	}
-}
-
-void ReadGameState_Aligned(Stream *in, RestoredData &r_data) {
-	AlignedStream align_s(in, Shared::kAligned_Read);
-	_GP(play).ReadFromSavegame(&align_s, kGSSvgVersion_OldFormat, r_data);
-}
-
-void restore_game_play_ex_data(Stream *in) {
-	char rbuffer[200];
-	for (size_t i = 0; i < _GP(play).do_once_tokens.size(); ++i) {
-		StrUtil::ReadCStr(rbuffer, in, sizeof(rbuffer));
-		_GP(play).do_once_tokens[i] = rbuffer;
-	}
-
-	in->ReadArrayOfInt32(&_GP(play).gui_draw_order[0], _GP(game).numgui);
-}
-
-void restore_game_play(Stream *in, RestoredData &r_data) {
-	int screenfadedout_was = _GP(play).screen_is_faded_out;
-	int roomchanges_was = _GP(play).room_changes;
-	// make sure the pointer is preserved
-	int32_t *gui_draw_order_was = _GP(play).gui_draw_order;
-
-	ReadGameState_Aligned(in, r_data);
-	r_data.Cameras[0].Flags = r_data.Camera0_Flags;
-
-	_GP(play).screen_is_faded_out = screenfadedout_was;
-	_GP(play).room_changes = roomchanges_was;
-	_GP(play).gui_draw_order = gui_draw_order_was;
-
-	restore_game_play_ex_data(in);
-}
-
-void ReadMoveList_Aligned(Stream *in) {
-	AlignedStream align_s(in, Shared::kAligned_Read);
-	for (int i = 0; i < _GP(game).numcharacters + MAX_ROOM_OBJECTS + 1; ++i) {
-		_G(mls)[i].ReadFromFile_Legacy(&align_s);
-
-		align_s.Reset();
-	}
-}
-
-void ReadGameSetupStructBase_Aligned(Stream *in) {
-	AlignedStream align_s(in, Shared::kAligned_Read);
-	_GP(game).GameSetupStructBase::ReadFromFile(&align_s);
-}
-
-void ReadCharacterExtras_Aligned(Stream *in) {
-	AlignedStream align_s(in, Shared::kAligned_Read);
-	for (int i = 0; i < _GP(game).numcharacters; ++i) {
-		_G(charextra)[i].ReadFromFile(&align_s);
-		align_s.Reset();
-	}
-}
-
-void restore_game_palette(Stream *in) {
-	in->SafeReadArray(&_G(palette)[0], PALETTE_COUNT);
-}
-
-void restore_game_dialogs(Stream *in) {
-	for (int vv = 0; vv < _GP(game).numdialog; vv++)
-		in->ReadArrayOfInt32(&_G(dialog)[vv].optionflags[0], MAXTOPICOPTIONS);
-}
-
-void restore_game_more_dynamic_values(Stream *in) {
-	_G(mouse_on_iface) = in->ReadInt32();
-	in->ReadInt32(); // mouse_on_iface_button
-	in->ReadInt32(); // mouse_pushed_iface
-	_G(ifacepopped) = in->ReadInt32();
-	_G(game_paused) = in->ReadInt32();
-}
-
-void ReadAnimatedButtons_Aligned(Stream *in) {
-	AlignedStream align_s(in, Shared::kAligned_Read);
-	for (int i = 0; i < _G(numAnimButs); ++i) {
-		_G(animbuts)[i].ReadFromFile(&align_s);
-		align_s.Reset();
-	}
-}
-
-HSaveError restore_game_gui(Stream *in, int numGuisWas) {
-	HError err = GUI::ReadGUI(_GP(guis), in, true);
-	if (!err)
-		return new SavegameError(kSvgErr_GameObjectInitFailed, err);
-	_GP(game).numgui = _GP(guis).size();
-
-	if (numGuisWas != _GP(game).numgui) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of GUI.");
-	}
-
-	_G(numAnimButs) = in->ReadInt32();
-	ReadAnimatedButtons_Aligned(in);
-	return HSaveError::None();
-}
-
-HSaveError restore_game_audiocliptypes(Stream *in) {
-	if (in->ReadInt32() != (int)_GP(game).audioClipTypes.size()) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of Audio Clip Types.");
-	}
-
-	for (size_t i = 0; i < _GP(game).audioClipTypes.size(); ++i) {
-		_GP(game).audioClipTypes[i].ReadFromFile(in);
-	}
-	return HSaveError::None();
-}
-
-void restore_game_thisroom(Stream *in, RestoredData &r_data) {
-	in->ReadArrayOfInt16(r_data.RoomLightLevels, MAX_ROOM_REGIONS);
-	in->ReadArrayOfInt32(r_data.RoomTintLevels, MAX_ROOM_REGIONS);
-	in->ReadArrayOfInt16(r_data.RoomZoomLevels1, MAX_WALK_AREAS + 1);
-	in->ReadArrayOfInt16(r_data.RoomZoomLevels2, MAX_WALK_AREAS + 1);
-}
-
-void restore_game_ambientsounds(Stream *in, RestoredData &r_data) {
-	for (int i = 0; i < MAX_SOUND_CHANNELS; ++i) {
-		_GP(ambient)[i].ReadFromFile(in);
-	}
-
-	for (int bb = 1; bb < MAX_SOUND_CHANNELS; bb++) {
-		if (_GP(ambient)[bb].channel == 0)
-			r_data.DoAmbient[bb] = 0;
-		else {
-			r_data.DoAmbient[bb] = _GP(ambient)[bb].num;
-			_GP(ambient)[bb].channel = 0;
-		}
-	}
-}
-
-void ReadOverlays_Aligned(Stream *in) {
-	AlignedStream align_s(in, Shared::kAligned_Read);
-	for (auto &over : _GP(screenover)) {
-		over.ReadFromFile(&align_s, 0);
-		align_s.Reset();
-	}
-}
-
-void restore_game_overlays(Stream *in) {
-	_GP(screenover).resize(in->ReadInt32());
-	ReadOverlays_Aligned(in);
-	for (auto &over : _GP(screenover)) {
-		if (over.hasSerializedBitmap)
-			over.pic = read_serialized_bitmap(in);
-	}
-}
-
-void restore_game_dynamic_surfaces(Stream *in, RestoredData &r_data) {
-	// load into a temp array since ccUnserialiseObjects will destroy
-	// it otherwise
-	r_data.DynamicSurfaces.resize(MAX_DYNAMIC_SURFACES);
-	for (int i = 0; i < MAX_DYNAMIC_SURFACES; ++i) {
-		if (in->ReadInt8() == 0) {
-			r_data.DynamicSurfaces[i] = nullptr;
-		} else {
-			r_data.DynamicSurfaces[i] = read_serialized_bitmap(in);
-		}
-	}
-}
-
-void restore_game_displayed_room_status(Stream *in, RestoredData &r_data) {
-	int bb;
-	for (bb = 0; bb < MAX_ROOM_BGFRAMES; bb++)
-		r_data.RoomBkgScene[bb].reset();
-
-	if (_G(displayed_room) >= 0) {
-
-		for (bb = 0; bb < MAX_ROOM_BGFRAMES; bb++) {
-			r_data.RoomBkgScene[bb] = nullptr;
-			if (_GP(play).raw_modified[bb]) {
-				r_data.RoomBkgScene[bb].reset(read_serialized_bitmap(in));
-			}
-		}
-		bb = in->ReadInt32();
-
-		if (bb)
-			_G(raw_saved_screen) = read_serialized_bitmap(in);
-
-		// get the current troom, in case they save in room 600 or whatever
-		ReadRoomStatus_Aligned(&_GP(troom), in);
-
-		if (_GP(troom).tsdatasize > 0) {
-			_GP(troom).tsdata = (char *)malloc(_GP(troom).tsdatasize + 5);
-			in->Read(&_GP(troom).tsdata[0], _GP(troom).tsdatasize);
-		} else
-			_GP(troom).tsdata = nullptr;
-	}
-}
-
-HSaveError restore_game_globalvars(Stream *in) {
-	if (in->ReadInt32() != _G(numGlobalVars)) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Restore game error: mismatching number of Global Variables.");
-	}
-
-	for (int i = 0; i < _G(numGlobalVars); ++i) {
-		_G(globalvars)[i].Read(in);
-	}
-	return HSaveError::None();
-}
-
-HSaveError restore_game_views(Stream *in) {
-	if (in->ReadInt32() != _GP(game).numviews) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of Views.");
-	}
-
-	for (int bb = 0; bb < _GP(game).numviews; bb++) {
-		for (int cc = 0; cc < _G(views)[bb].numLoops; cc++) {
-			for (int dd = 0; dd < _G(views)[bb].loops[cc].numFrames; dd++) {
-				_G(views)[bb].loops[cc].frames[dd].sound = in->ReadInt32();
-				_G(views)[bb].loops[cc].frames[dd].pic = in->ReadInt32();
-			}
-		}
-	}
-	return HSaveError::None();
-}
-
-HSaveError restore_game_audioclips_and_crossfade(Stream *in, RestoredData &r_data) {
-	if (in->ReadInt32() != (int)_GP(game).audioClips.size()) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of Audio Clips.");
-	}
-
-	for (int i = 0; i <= MAX_SOUND_CHANNELS; ++i) {
-		RestoredData::ChannelInfo &chan_info = r_data.AudioChans[i];
-		chan_info.Pos = 0;
-		chan_info.ClipID = in->ReadInt32();
-		if (chan_info.ClipID >= 0) {
-			if (chan_info.ClipID >= (int)_GP(game).audioClips.size()) {
-				return new SavegameError(kSvgErr_GameObjectInitFailed, "Invalid audio clip index.");
-			}
-
-			chan_info.Pos = in->ReadInt32();
-			if (chan_info.Pos < 0)
-				chan_info.Pos = 0;
-			chan_info.Priority = in->ReadInt32();
-			chan_info.Repeat = in->ReadInt32();
-			chan_info.Vol = in->ReadInt32();
-			chan_info.Pan = in->ReadInt32();
-			chan_info.VolAsPercent = in->ReadInt32();
-			chan_info.PanAsPercent = in->ReadInt32();
-			chan_info.Speed = 1000;
-			if (_G(loaded_game_file_version) >= kGameVersion_340_2)
-				chan_info.Speed = in->ReadInt32();
-		}
 	}
-	_G(crossFading) = in->ReadInt32();
-	_G(crossFadeVolumePerStep) = in->ReadInt32();
-	_G(crossFadeStep) = in->ReadInt32();
-	_G(crossFadeVolumeAtStart) = in->ReadInt32();
-	return HSaveError::None();
 }
 
-HSaveError restore_game_data(Stream *in, SavegameVersion svg_version, const PreservedParams &pp, RestoredData &r_data) {
-	int vv;
-
-	HSaveError err = restore_game_head_dynamic_values(in, r_data);
-	if (!err)
-		return err;
-	restore_game_spriteset(in);
-
-	update_polled_stuff_if_runtime();
-
-	err = restore_game_scripts(in, pp, r_data);
-	if (!err)
-		return err;
-	restore_game_room_state(in);
-	restore_game_play(in, r_data);
-	ReadMoveList_Aligned(in);
-
-	// save pointer members before reading
-	char *gswas = _GP(game).globalscript;
-	ccScript *compsc = _GP(game).compiled_script;
-	CharacterInfo *chwas = _GP(game).chars;
-	WordsDictionary *olddict = _GP(game).dict;
-	char *mesbk[MAXGLOBALMES];
-	int numchwas = _GP(game).numcharacters;
-	for (vv = 0; vv < MAXGLOBALMES; vv++) mesbk[vv] = _GP(game).messages[vv];
-	int numdiwas = _GP(game).numdialog;
-	int numinvwas = _GP(game).numinvitems;
-	int numviewswas = _GP(game).numviews;
-	int numGuisWas = _GP(game).numgui;
-
-	ReadGameSetupStructBase_Aligned(in);
-
-	// Delete unneeded data
-	// TODO: reorganize this (may be solved by optimizing safe format too)
-	delete [] _GP(game).load_messages;
-	_GP(game).load_messages = nullptr;
-
-	if (_GP(game).numdialog != numdiwas) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of Dialogs.");
-	}
-	if (numchwas != _GP(game).numcharacters) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of Characters.");
-	}
-	if (numinvwas != _GP(game).numinvitems) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of Inventory Items.");
-	}
-	if (_GP(game).numviews != numviewswas) {
-		return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of Views.");
-	}
-
-	_GP(game).ReadFromSaveGame_v321(in, gswas, compsc, chwas, olddict, mesbk);
-
-	// Modified custom properties are read separately to keep existing save format
-	_GP(play).ReadCustomProperties_v340(in);
-
-	ReadCharacterExtras_Aligned(in);
-	restore_game_palette(in);
-	restore_game_dialogs(in);
-	restore_game_more_dynamic_values(in);
-	err = restore_game_gui(in, numGuisWas);
-	if (!err)
-		return err;
-	err = restore_game_audiocliptypes(in);
-	if (!err)
-		return err;
-	restore_game_thisroom(in, r_data);
-	restore_game_ambientsounds(in, r_data);
-	restore_game_overlays(in);
-
-	update_polled_stuff_if_runtime();
-
-	restore_game_dynamic_surfaces(in, r_data);
-
-	update_polled_stuff_if_runtime();
-
-	restore_game_displayed_room_status(in, r_data);
-	err = restore_game_globalvars(in);
-	if (!err)
-		return err;
-	err = restore_game_views(in);
-	if (!err)
-		return err;
-
-	if (in->ReadInt32() != (int32)(MAGICNUMBER + 1)) {
-		return new SavegameError(kSvgErr_InconsistentFormat, "MAGICNUMBER not found before Audio Clips.");
-	}
-
-	err = restore_game_audioclips_and_crossfade(in, r_data);
-	if (!err)
-		return err;
-
-	auto pluginFileHandle = AGSE_RESTOREGAME;
-	pl_set_file_handle(pluginFileHandle, in);
-	pl_run_plugin_hooks(AGSE_RESTOREGAME, pluginFileHandle);
-	pl_clear_file_handle();
-	if (in->ReadInt32() != (int32)MAGICNUMBER)
-		return new SavegameError(kSvgErr_InconsistentPlugin);
-
-	// save the new room music vol for later use
-	r_data.RoomVolume = (RoomVolumeMod)in->ReadInt32();
-
-	if (ccUnserializeAllObjects(in, &_GP(ccUnserializer))) {
-		return new SavegameError(kSvgErr_GameObjectInitFailed,
-		                         String::FromFormat("Managed pool deserialization failed: %s.", _G(ccErrorString).GetCStr()));
-	}
-
-	// preserve legacy music type setting
-	_G(current_music_type) = in->ReadInt32();
-
-	return HSaveError::None();
-}
+int gameHasBeenRestored = 0;
+int oldeip;
 
 bool read_savedgame_description(const String &savedgame, String &description) {
 	SavegameDescription desc;
-	if (OpenSavegame(savedgame, desc, kSvgDesc_UserText)) {
-		description = desc.UserText;
-		return true;
+	HSaveError err = OpenSavegame(savedgame, desc, kSvgDesc_UserText);
+	if (!err) {
+		Debug::Printf(kDbgMsg_Error, "Unable to read save's description.\n%s", err->FullMessage().GetCStr());
+		return false;
 	}
-	return false;
+	description = desc.UserText;
+	return true;
 }
 
 bool read_savedgame_screenshot(const String &savedgame, int &want_shot) {
@@ -1421,8 +939,10 @@ bool read_savedgame_screenshot(const String &savedgame, int &want_shot) {
 
 	SavegameDescription desc;
 	HSaveError err = OpenSavegame(savedgame, desc, kSvgDesc_UserImage);
-	if (!err)
+	if (!err) {
+		Debug::Printf(kDbgMsg_Error, "Unable to read save's screenshot.\n%s", err->FullMessage().GetCStr());
 		return false;
+	}
 
 	if (desc.UserImage.get()) {
 		int slot = _GP(spriteset).GetFreeIndex();
@@ -1435,18 +955,31 @@ bool read_savedgame_screenshot(const String &savedgame, int &want_shot) {
 	return true;
 }
 
-HSaveError load_game(int slotNumber, bool &data_overwritten) {
+
+// Test if the game file contains expected GUID / legacy id
+bool test_game_guid(const String &filepath, const String &guid, int legacy_id) {
+	MainGameSource src;
+	HGameFileError err = OpenMainGameFileFromDefaultAsset(src);
+	if (!err)
+		return false;
+	GameSetupStruct g;
+	PreReadGameData(g, src.InputStream.get(), src.DataVersion);
+	if (!guid.IsEmpty())
+		return guid.CompareNoCase(g.guid) == 0;
+	return legacy_id == g.uniqueid;
+}
+
+HSaveError load_game(const String &path, int slotNumber, bool &data_overwritten) {
+#ifdef TODO
 	data_overwritten = false;
-	_G(gameHasBeenRestored)++;
+	gameHasBeenRestored++;
 
-	_G(oldeip) = _G(our_eip);
+	oldeip = _G(our_eip);
 	_G(our_eip) = 2050;
 
 	HSaveError err;
 	SavegameSource src;
 	SavegameDescription desc;
-
-	String path = get_save_game_path(slotNumber);
 	err = OpenSavegame(path, src, desc, kSvgDesc_EnvInfo);
 
 	// saved in incompatible enviroment
@@ -1457,46 +990,70 @@ HSaveError load_game(int slotNumber, bool &data_overwritten) {
 		return new SavegameError(kSvgErr_DifferentColorDepth, String::FromFormat("Running: %d-bit, saved in: %d-bit.", _GP(game).GetColorDepth(), desc.ColorDepth));
 
 	// saved with different game file
-	if (Path::ComparePaths(desc.MainDataFilename, _GP(ResPaths).GamePak.Name)) {
-		// [IKM] 2012-11-26: this is a workaround, indeed.
-		// Try to find wanted game's executable; if it does not exist,
-		// continue loading savedgame in current game, and pray for the best
-		get_install_dir_path(_G(gamefilenamebuf), desc.MainDataFilename);
-		if (Shared::File::TestReadFile(_G(gamefilenamebuf))) {
+	// if savegame is modern enough then test game GUIDs
+	if (!desc.GameGuid.IsEmpty() || desc.LegacyID != 0) {
+		if (desc.GameGuid.Compare(_GP(game).guid) != 0 && desc.LegacyID != _GP(game).uniqueid) {
+			// Try to find wanted game's data using game id
+			String gamefile = FindGameData(_GP(ResPaths).DataDir,
+			[&desc](const String & filepath) {
+				return test_game_guid(filepath, desc.GameGuid, desc.LegacyID);
+			});
+			if (Shared::File::TestReadFile(gamefile)) {
+				RunAGSGame(desc.MainDataFilename, 0, 0);
+				_G(load_new_game_restore) = slotNumber;
+				return HSaveError::None();
+			}
+			return new SavegameError(kSvgErr_GameGuidMismatch);
+		}
+	}
+	// if it's old then do the stupid old-style filename test
+	// TODO: remove filename test after deprecating old saves
+	else if (desc.MainDataFilename.Compare(_GP(ResPaths).GamePak.Name)) {
+		String gamefile = Path::ConcatPaths(_GP(ResPaths).DataDir, desc.MainDataFilename);
+		if (Shared::File::TestReadFile(gamefile)) {
 			RunAGSGame(desc.MainDataFilename, 0, 0);
 			_G(load_new_game_restore) = slotNumber;
 			return HSaveError::None();
 		}
-		Shared::Debug::Printf(kDbgMsg_Warn, "WARNING: the saved game '%s' references game file '%s', but it cannot be found in the current directory. Trying to restore in the running game instead.",
-		                      path.GetCStr(), desc.MainDataFilename.GetCStr());
+		// if it does not exist, continue loading savedgame in current game, and pray for the best
+		Shared::Debug::Printf(kDbgMsg_Warn, "WARNING: the saved game '%s' references game file '%s' (title: '%s'), but it cannot be found in the current directory. Trying to restore in the running game instead.",
+		                      path.GetCStr(), desc.MainDataFilename.GetCStr(), desc.GameTitle.GetCStr());
 	}
 
 	// do the actual restore
-	err = RestoreGameState(src.InputStream, src.Version);
+	err = RestoreGameState(src.InputStream.get(), src.Version);
 	data_overwritten = true;
 	if (!err)
 		return err;
 	src.InputStream.reset();
-	_G(our_eip) = _G(oldeip);
+	_G(our_eip) = oldeip;
 
 	// ensure keyboard buffer is clean
 	ags_clear_input_buffer();
 	// call "After Restore" event callback
 	run_on_event(GE_RESTORE_GAME, RuntimeScriptValue().SetInt32(slotNumber));
 	return HSaveError::None();
+#else
+	error("TODO: load_game");
+#endif
 }
 
 bool try_restore_save(int slot) {
+	return try_restore_save(get_save_game_path(slot), slot);
+}
+
+bool try_restore_save(const Shared::String &path, int slot) {
 	bool data_overwritten;
-	HSaveError err = load_game(slot, data_overwritten);
+	HSaveError err = load_game(path, slot, data_overwritten);
 	if (!err) {
-		String error = String::FromFormat("Unable to restore the saved game.\n%s",
+		String error = String::FromFormat("Unable to restore the saved _GP(game).\n%s",
 		                                  err->FullMessage().GetCStr());
+		Debug::Printf(kDbgMsg_Error, "%s", error.GetCStr());
 		// currently AGS cannot properly revert to stable state if some of the
 		// game data was released or overwritten by the data from save file,
 		// this is why we tell engine to shutdown if that happened.
 		if (data_overwritten)
-			quitprintf(error);
+			quitprintf("%s", error.GetCStr());
 		else
 			Display(error);
 		return false;
@@ -1528,7 +1085,7 @@ bool check_skip_cutscene_keypress(int kgn) {
 
 	CutsceneSkipStyle skip = get_cutscene_skipstyle();
 	if (skip == eSkipSceneAnyKey || skip == eSkipSceneKeyMouse ||
-	        (kgn == 27 && (skip == eSkipSceneEscOnly || skip == eSkipSceneEscOrRMB))) {
+	        (kgn == eAGSKeyCodeEscape && (skip == eSkipSceneEscOnly || skip == eSkipSceneEscOrRMB))) {
 		start_skipping_cutscene();
 		return true;
 	}
@@ -1538,7 +1095,7 @@ bool check_skip_cutscene_keypress(int kgn) {
 bool check_skip_cutscene_mclick(int mbut) {
 	CutsceneSkipStyle skip = get_cutscene_skipstyle();
 	if (skip == eSkipSceneMouse || skip == eSkipSceneKeyMouse ||
-	        (mbut == RIGHT && skip == eSkipSceneEscOrRMB)) {
+	        (mbut == MouseRight && skip == eSkipSceneEscOrRMB)) {
 		start_skipping_cutscene();
 		return true;
 	}
@@ -1656,22 +1213,17 @@ void display_switch_out() {
 	ags_clear_input_buffer();
 	// Always unlock mouse when switching out from the game
 	_GP(mouse).UnlockFromWindow();
-	_G(platform)->DisplaySwitchOut();
-	_G(platform)->ExitFullscreenMode();
 }
 
+// Called when game looses input focus and must pause until focus is returned
 void display_switch_out_suspend() {
-	// this is only called if in SWITCH_PAUSE mode
-	//debug_script_warn("display_switch_out");
 	display_switch_out();
 
 	_G(switching_away_from_game)++;
 
 	_G(platform)->PauseApplication();
 
-	// allow background running temporarily to halt the sound
-	if (set_display_switch_mode(SWITCH_BACKGROUND) == -1)
-		set_display_switch_mode(SWITCH_BACKAMNESIA);
+	// TODO: find out if anything has to be done here for SDL backend
 
 	{
 		// stop the sound stuttering
@@ -1684,8 +1236,6 @@ void display_switch_out_suspend() {
 		}
 	} // -- AudioChannelsLock
 
-	_G(platform)->Delay(1000);
-
 	// restore the callbacks
 	SetMultitasking(0);
 
@@ -1695,18 +1245,13 @@ void display_switch_out_suspend() {
 // Called whenever game gets input focus
 void display_switch_in() {
 	_G(switched_away) = false;
-	if (_G(gfxDriver)) {
-		DisplayMode mode = _G(gfxDriver)->GetDisplayMode();
-		if (!mode.Windowed)
-			_G(platform)->EnterFullscreenMode(mode);
-	}
-	_G(platform)->DisplaySwitchIn();
 	ags_clear_input_buffer();
 	// If auto lock option is set, lock mouse to the game window
 	if (_GP(usetup).mouse_auto_lock && _GP(scsystem).windowed)
 		_GP(mouse).TryLockToWindow();
 }
 
+// Called when game gets input focus and must resume after pause
 void display_switch_in_resume() {
 	display_switch_in();
 
@@ -1724,6 +1269,8 @@ void display_switch_in_resume() {
 	if (_G(gfxDriver) && _G(gfxDriver)->UsesMemoryBackBuffer())
 		_G(gfxDriver)->ClearRectangle(0, 0, _GP(game).GetGameRes().Width - 1, _GP(game).GetGameRes().Height - 1, nullptr);
 
+	// TODO: find out if anything has to be done here for SDL backend
+
 	_G(platform)->ResumeApplication();
 }
 
@@ -1813,6 +1360,82 @@ bool unserialize_audio_script_object(int index, const char *objectType, const ch
 	return true;
 }
 
+void game_sprite_updated(int sprnum) {
+	// Check if this sprite is assigned to any game object, and update them if necessary
+	// room objects cache
+	if (_G(croom) != nullptr) {
+		for (size_t i = 0; i < (size_t)_G(croom)->numobj; ++i) {
+			if (_G(objs)[i].num == sprnum)
+				_G(objcache)[i].sppic = -1;
+		}
+	}
+	// character cache
+	for (size_t i = 0; i < (size_t)_GP(game).numcharacters; ++i) {
+		if (_G(charcache)[i].sppic == sprnum)
+			_G(charcache)[i].sppic = -1;
+	}
+	// gui backgrounds
+	for (size_t i = 0; i < (size_t)_GP(game).numgui; ++i) {
+		if (_GP(guis)[i].BgImage == sprnum) {
+			_GP(guis)[i].MarkChanged();
+		}
+	}
+	// gui buttons
+	for (size_t i = 0; i < (size_t)_G(numguibuts); ++i) {
+		if (_GP(guibuts)[i].CurrentImage == sprnum) {
+			_GP(guibuts)[i].NotifyParentChanged();
+		}
+	}
+}
+
+void game_sprite_deleted(int sprnum) {
+	// Check if this sprite is assigned to any game object, and update them if necessary
+	// room objects and their cache
+	if (_G(croom) != nullptr) {
+		for (size_t i = 0; i < (size_t)_G(croom)->numobj; ++i) {
+			if (_G(objs)[i].num == sprnum) {
+				_G(objs)[i].num = 0;
+				_G(objcache)[i].sppic = -1;
+			}
+		}
+	}
+	// character cache
+	for (size_t i = 0; i < (size_t)_GP(game).numcharacters; ++i) {
+		if (_G(charcache)[i].sppic == sprnum)
+			_G(charcache)[i].sppic = -1;
+	}
+	// gui backgrounds
+	for (size_t i = 0; i < (size_t)_GP(game).numgui; ++i) {
+		if (_GP(guis)[i].BgImage == sprnum) {
+			_GP(guis)[i].BgImage = 0;
+			_GP(guis)[i].MarkChanged();
+		}
+	}
+	// gui buttons
+	for (size_t i = 0; i < (size_t)_G(numguibuts); ++i) {
+		if (_GP(guibuts)[i].Image == sprnum)
+			_GP(guibuts)[i].Image = 0;
+		if (_GP(guibuts)[i].MouseOverImage == sprnum)
+			_GP(guibuts)[i].MouseOverImage = 0;
+		if (_GP(guibuts)[i].PushedImage == sprnum)
+			_GP(guibuts)[i].PushedImage = 0;
+
+		if (_GP(guibuts)[i].CurrentImage == sprnum) {
+			_GP(guibuts)[i].CurrentImage = 0;
+			_GP(guibuts)[i].NotifyParentChanged();
+		}
+	}
+	// _G(views)
+	for (size_t v = 0; v < (size_t)_GP(game).numviews; ++v) {
+		for (size_t l = 0; l < (size_t)_G(views)[v].numLoops; ++l) {
+			for (size_t f = 0; f < (size_t)_G(views)[v].loops[l].numFrames; ++f) {
+				if (_G(views)[v].loops[l].frames[f].pic == sprnum)
+					_G(views)[v].loops[l].frames[f].pic = 0;
+			}
+		}
+	}
+}
+
 //=============================================================================
 //
 // Script API Functions
diff --git a/engines/ags/engine/ac/game.h b/engines/ags/engine/ac/game.h
index e8deb022f7..082866ddf3 100644
--- a/engines/ags/engine/ac/game.h
+++ b/engines/ags/engine/ac/game.h
@@ -29,13 +29,12 @@
 #ifndef AGS_ENGINE_AC_GAME_H
 #define AGS_ENGINE_AC_GAME_H
 
-#include "ags/engine/ac/dynobj/scriptviewframe.h"
+#include "ags/engine/ac/dynobj/script_view_frame.h"
 #include "ags/engine/main/game_file.h"
 #include "ags/shared/util/string.h"
 
 namespace AGS3 {
 
-// Forward declaration
 namespace AGS {
 namespace Shared {
 class Bitmap;
@@ -152,6 +151,7 @@ void restore_after_dialog();
 Shared::String get_save_game_directory();
 Shared::String get_save_game_suffix();
 void set_save_game_suffix(const Shared::String &suffix);
+// Returns full path to the save for the given slot number
 Shared::String get_save_game_path(int slotNum);
 void restore_game_dialog();
 void save_game_dialog();
@@ -164,6 +164,7 @@ bool read_savedgame_screenshot(const Shared::String &savedgame, int &want_shot);
 // Tries to restore saved game and displays an error on failure; if the error occured
 // too late, when the game data was already overwritten, shuts engine down.
 bool try_restore_save(int slot);
+bool try_restore_save(const Shared::String &path, int slot);
 void serialize_bitmap(const Shared::Bitmap *thispic, Shared::Stream *out);
 // On Windows we could just use IIDFromString but this is platform-independant
 void convert_guid_from_text_to_binary(const char *guidText, unsigned char *buffer);
@@ -196,6 +197,14 @@ void get_message_text(int msnum, char *buffer, char giveErr = 1);
 
 bool unserialize_audio_script_object(int index, const char *objectType, const char *serializedData, int dataSize);
 
+// Notifies the game objects that certain sprite was updated.
+// This make them update their render states, caches, and so on.
+void game_sprite_updated(int sprnum);
+// Notifies the game objects that certain sprite was deleted.
+// Those which used that sprite will reset to dummy sprite 0, update their render states and caches.
+void game_sprite_deleted(int sprnum);
+
+
 extern void set_loop_counter(unsigned int new_counter);
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/gamesetup.cpp b/engines/ags/engine/ac/game_setup.cpp
similarity index 92%
rename from engines/ags/engine/ac/gamesetup.cpp
rename to engines/ags/engine/ac/game_setup.cpp
index adf07e0196..43b1762efa 100644
--- a/engines/ags/engine/ac/gamesetup.cpp
+++ b/engines/ags/engine/ac/game_setup.cpp
@@ -20,12 +20,12 @@
  *
  */
 
-#include "ags/shared/util/wgt2allg.h" // DIGI_AUTODETECT & MIDI_AUTODETECT
-#include "ags/engine/ac/gamesetup.h"
+#include "ags/engine/ac/game_setup.h"
 
 namespace AGS3 {
 
 GameSetup::GameSetup() {
+	local_user_conf = false;
 	audio_backend = 1;
 	no_speech_pack = false;
 	textheight = 0;
@@ -37,7 +37,7 @@ GameSetup::GameSetup() {
 	override_upscale = false;
 	mouse_speed = 1.f;
 	mouse_ctrl_when = kMouseCtrl_Fullscreen;
-	mouse_ctrl_enabled = true;
+	mouse_ctrl_enabled = false;
 	mouse_speed_def = kMouseSpeed_CurrentDisplay;
 	RenderAtScreenRes = false;
 	Supersampling = 1;
diff --git a/engines/ags/engine/ac/gamesetup.h b/engines/ags/engine/ac/game_setup.h
similarity index 75%
rename from engines/ags/engine/ac/gamesetup.h
rename to engines/ags/engine/ac/game_setup.h
index 3bce390839..113494f7e4 100644
--- a/engines/ags/engine/ac/gamesetup.h
+++ b/engines/ags/engine/ac/game_setup.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GAMESETUP_H
-#define AGS_ENGINE_AC_GAMESETUP_H
+#ifndef AGS_ENGINE_AC_GAME_SETUP_H
+#define AGS_ENGINE_AC_GAME_SETUP_H
 
 #include "ags/engine/main/graphics_mode.h"
 #include "ags/shared/util/string.h"
@@ -53,17 +53,23 @@ using AGS::Shared::String;
 // that engine may use a "config" object or combo of objects to store
 // current user config, which may also be changed from script, and saved.
 struct GameSetup {
-	int audio_backend; // abstract option, currently only works as on/off
+	int    audio_backend; // abstract option, currently only works as on/off
 	int textheight; // text height used on the certain built-in GUI // TODO: move out to game class?
 	bool  no_speech_pack;
 	bool  enable_antialiasing;
 	bool  disable_exception_handling;
-	String data_files_dir;
-	String main_data_filename;
-	String main_data_filepath;
-	String install_dir; // optional custom install dir path
-	String install_audio_dir; // optional custom install audio dir path
-	String install_voice_dir; // optional custom install voice-over dir path
+	String startup_dir; // directory where the default game config is located (usually same as main_data_dir)
+	String main_data_dir; // main data directory
+	String main_data_file; // full path to main data file
+	// Following 4 optional dirs are currently for compatibility with Editor only (debug runs)
+	// This is bit ugly, but remain so until more flexible configuration is designed
+	String install_dir; // optional custom install dir path (also used as extra data dir)
+	String opt_data_dir; // optional data dir number 2
+	String opt_audio_dir; // optional custom install audio dir path
+	String opt_voice_dir; // optional custom install voice-over dir path
+	//
+	String conf_path; // explicitly set path to config
+	bool   local_user_conf; // search for user config in the game directory
 	String user_data_dir; // directory to write savedgames and user files to
 	String shared_data_dir; // directory to write shared game files to
 	String translation;
diff --git a/engines/ags/engine/ac/gamestate.cpp b/engines/ags/engine/ac/game_state.cpp
similarity index 92%
rename from engines/ags/engine/ac/gamestate.cpp
rename to engines/ags/engine/ac/game_state.cpp
index d5fd3debe1..b6f49fa851 100644
--- a/engines/ags/engine/ac/gamestate.cpp
+++ b/engines/ags/engine/ac/game_state.cpp
@@ -23,20 +23,20 @@
 #include "ags/lib/std/algorithm.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/shared/ac/game_version.h"
-#include "ags/engine/ac/gamestate.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/engine/ac/game_state.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/timer.h"
-#include "ags/engine/ac/dynobj/scriptcamera.h"
-#include "ags/engine/ac/dynobj/scriptsystem.h"
-#include "ags/engine/ac/dynobj/scriptviewport.h"
+#include "ags/engine/ac/dynobj/script_camera.h"
+#include "ags/engine/ac/dynobj/script_system.h"
+#include "ags/engine/ac/dynobj/script_viewport.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/engine/device/mousew32.h"
-#include "ags/shared/game/customproperties.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/engine/device/mouse_w32.h"
+#include "ags/shared/game/custom_properties.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/engine/game/savegame_internal.h"
 #include "ags/engine/main/engine.h"
 #include "ags/engine/media/audio/audio_system.h"
-#include "ags/shared/util/alignedstream.h"
+#include "ags/shared/util/aligned_stream.h"
 #include "ags/shared/util/string_utils.h"
 #include "ags/globals.h"
 
@@ -46,22 +46,8 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 GameState::GameState() {
-	Common::fill(&globalvars[0], &globalvars[MAXGLOBALVARS], 0);
-	Common::fill(&reserved[0], &reserved[GAME_STATE_RESERVED_INTS], 0);
-	Common::fill(&globalscriptvars[0], &globalscriptvars[MAXGSVALUES], 0);
-	Common::fill(&walkable_areas_on[0], &walkable_areas_on[MAX_WALK_AREAS + 1], 0);
-	Common::fill(&script_timers[0], &script_timers[MAX_TIMERS], 0);
-	Common::fill(&parsed_words[0], &parsed_words[MAX_PARSED_WORDS], 0);
-	Common::fill(&bad_parsed_word[0], &bad_parsed_word[100], 0);
-	Common::fill(&raw_modified[0], &raw_modified[MAX_ROOM_BGFRAMES], 0);
-	Common::fill(&filenumbers[0], &filenumbers[MAXSAVEGAMES], 0);
-	Common::fill(&music_queue[0], &music_queue[MAX_QUEUED_MUSIC], 0);
-	Common::fill(&takeover_from[0], &takeover_from[50], 0);
-	Common::fill(&playmp3file_name[0], &playmp3file_name[PLAYMP3FILE_MAX_FILENAME_LEN], 0);
-	Common::fill(&globalstrings[0][0], &globalstrings[MAXGLOBALSTRINGS - 1][MAX_MAXSTRLEN], 0);
-	Common::fill(&lastParserEntry[0], &lastParserEntry[MAX_MAXSTRLEN], 0);
-	Common::fill(&game_name[0], &game_name[100], 0);
-	Common::fill(&default_audio_type_volumes[0], &default_audio_type_volumes[MAX_AUDIO_TYPES], 0);
+	_isAutoRoomViewport = true;
+	_mainViewportHasChanged = false;
 }
 
 void GameState::Free() {
@@ -79,7 +65,7 @@ void GameState::SetAutoRoomViewport(bool on) {
 
 void GameState::SetMainViewport(const Rect &viewport) {
 	_mainViewport.SetRect(viewport);
-	_GP(mouse).SetGraphicArea();
+	_GP(mouse).UpdateGraphicArea();
 	_GP(scsystem).viewport_width = game_to_data_coord(_mainViewport.GetRect().GetWidth());
 	_GP(scsystem).viewport_height = game_to_data_coord(_mainViewport.GetRect().GetHeight());
 	_mainViewportHasChanged = true;
@@ -183,8 +169,6 @@ void GameState::UpdateRoomCamera(int index) {
 			int y = data_to_game_coord(_G(playerchar)->y) - rc.GetHeight() / 2;
 			cam->SetAt(x, y);
 		}
-	} else {
-		cam->SetAt(0, 0);
 	}
 }
 
@@ -244,7 +228,7 @@ PViewport GameState::CreateRoomViewport() {
 	viewport->SetRect(_mainViewport.GetRect());
 	ScriptViewport *scv = new ScriptViewport(index);
 	_roomViewports.push_back(viewport);
-	_scViewportRefs.push_back(std::make_pair(scv, (int32_t)0));
+	_scViewportRefs.push_back(std::make_pair(scv, 0));
 	_roomViewportsSorted.push_back(viewport);
 	_roomViewportZOrderChanged = true;
 	on_roomviewport_created(index);
@@ -301,7 +285,7 @@ PCamera GameState::CreateRoomCamera() {
 	camera->SetAt(0, 0);
 	camera->SetSize(_mainViewport.GetRect().GetSize());
 	ScriptCamera *scam = new ScriptCamera(index);
-	_scCameraRefs.push_back(std::make_pair(scam, (int32_t)0));
+	_scCameraRefs.push_back(std::make_pair(scam, 0));
 	_roomCameras.push_back(camera);
 	return camera;
 }
@@ -379,7 +363,7 @@ bool GameState::IsNonBlockingVoiceSpeech() const {
 
 bool GameState::ShouldPlayVoiceSpeech() const {
 	return !_GP(play).fast_forward &&
-		(_GP(play).want_speech >= 1) && (!_GP(ResPaths).SpeechPak.Name.IsEmpty());
+	       (_GP(play).want_speech >= 1) && (!_GP(ResPaths).SpeechPak.Name.IsEmpty());
 }
 
 void GameState::ReadFromSavegame(Shared::Stream *in, GameStateSvgVersion svg_ver, RestoredData &r_data) {
@@ -472,7 +456,7 @@ void GameState::ReadFromSavegame(Shared::Stream *in, GameStateSvgVersion svg_ver
 	dialog_options_highlight_color = in->ReadInt32();
 	if (old_save)
 		in->ReadArrayOfInt32(reserved, GAME_STATE_RESERVED_INTS);
-	// ** up to here is referenced in the script "_GP(game)." object
+	// ** up to here is referenced in the script "game." object
 	if (old_save) {
 		in->ReadInt32(); // recording
 		in->ReadInt32(); // playback
@@ -500,7 +484,7 @@ void GameState::ReadFromSavegame(Shared::Stream *in, GameStateSvgVersion svg_ver
 	digital_master_volume = in->ReadInt32();
 	in->Read(walkable_areas_on, MAX_WALK_AREAS + 1);
 	screen_flipped = in->ReadInt16();
-	if (svg_ver < kGSSvgVersion_3510) {
+	if (svg_ver < kGSSvgVersion_350_10) {
 		short offsets_locked = in->ReadInt16();
 		if (offsets_locked != 0)
 			r_data.Camera0_Flags = kSvgCamPosLocked;
@@ -594,11 +578,11 @@ void GameState::ReadFromSavegame(Shared::Stream *in, GameStateSvgVersion svg_ver
 	}
 	text_min_display_time_ms = in->ReadInt32();
 	ignore_user_input_after_text_timeout_ms = in->ReadInt32();
-	if (svg_ver < kGSSvgVersion_3509)
+	if (svg_ver < kGSSvgVersion_350_9)
 		in->ReadInt32(); // ignore_user_input_until_time -- do not apply from savegame
 	if (old_save)
 		in->ReadArrayOfInt32(default_audio_type_volumes, MAX_AUDIO_TYPES);
-	if (svg_ver >= kGSSvgVersion_3509) {
+	if (svg_ver >= kGSSvgVersion_350_9) {
 		int voice_speech_flags = in->ReadInt32();
 		speech_has_voice = voice_speech_flags != 0;
 		speech_voice_blocking = (voice_speech_flags & 0x02) != 0;
@@ -688,13 +672,13 @@ void GameState::WriteForSavegame(Shared::Stream *out) const {
 	out->WriteInt32(speech_portrait_y);
 	out->WriteInt32(speech_display_post_time_ms);
 	out->WriteInt32(dialog_options_highlight_color);
-	// ** up to here is referenced in the script "_GP(game)." object
+	// ** up to here is referenced in the script "game." object
 	out->WriteInt32(randseed);    // random seed
-	out->WriteInt32(player_on_region);     // player's current region
+	out->WriteInt32(player_on_region);    // player's current region
 	out->WriteInt32(check_interaction_only);
 	out->WriteInt32(bg_frame);
-	out->WriteInt32(bg_anim_delay);   // for animating backgrounds
-	out->WriteInt32(music_vol_was);   // before the volume drop
+	out->WriteInt32(bg_anim_delay);  // for animating backgrounds
+	out->WriteInt32(music_vol_was);  // before the volume drop
 	out->WriteInt16(wait_counter);
 	out->WriteInt16(mboundx1);
 	out->WriteInt16(mboundx2);
@@ -860,8 +844,8 @@ HorAlignment ConvertLegacyScriptAlignment(LegacyScriptAlignment align) {
 // Alignment constants in the Script API and still support old version.
 HorAlignment ReadScriptAlignment(int32_t align) {
 	return _GP(game).options[OPT_BASESCRIPTAPI] < kScriptAPI_v350 ?
-		ConvertLegacyScriptAlignment((LegacyScriptAlignment)align) :
-		(HorAlignment)align;
+	       ConvertLegacyScriptAlignment((LegacyScriptAlignment)align) :
+	       (HorAlignment)align;
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/gamestate.h b/engines/ags/engine/ac/game_state.h
similarity index 56%
rename from engines/ags/engine/ac/gamestate.h
rename to engines/ags/engine/ac/game_state.h
index a06a564250..9be2028fe7 100644
--- a/engines/ags/engine/ac/gamestate.h
+++ b/engines/ags/engine/ac/game_state.h
@@ -20,16 +20,16 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GAMESTATE_H
-#define AGS_ENGINE_AC_GAMESTATE_H
+#ifndef AGS_ENGINE_AC_GAME_STATE_H
+#define AGS_ENGINE_AC_GAME_STATE_H
 
 #include "ags/lib/std/memory.h"
 #include "ags/lib/std/vector.h"
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/engine/ac/runtime_defines.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/engine/game/viewport.h"
-#include "ags/engine/media/audio/queuedaudioitem.h"
+#include "ags/engine/media/audio/queued_audio_item.h"
 #include "ags/shared/util/geometry.h"
 #include "ags/shared/util/string_types.h"
 #include "ags/shared/util/string.h"
@@ -49,8 +49,8 @@ namespace Engine {
 struct RestoredData;
 } // namespace Engine
 } // namespace AGS
-using namespace AGS; // FIXME later
 
+using namespace AGS; // FIXME later
 struct ScriptViewport;
 struct ScriptCamera;
 
@@ -61,172 +61,171 @@ enum GameStateSvgVersion {
 	kGSSvgVersion_OldFormat = -1, // TODO: remove after old save support is dropped
 	kGSSvgVersion_Initial = 0,
 	kGSSvgVersion_350 = 1,
-	kGSSvgVersion_3509 = 2,
-	kGSSvgVersion_3510 = 3,
+	kGSSvgVersion_350_9 = 2,
+	kGSSvgVersion_350_10 = 3,
 };
 
 
+
 // Adding to this might need to modify AGSDEFNS.SH and AGSPLUGIN.H
 struct GameState {
-	int  score = 0;      // player's current score
-	int  usedmode = 0;   // set by ProcessClick to last cursor mode used
-	int  disabled_user_interface = 0;  // >0 while in cutscene/etc
-	int  gscript_timer = 0;    // obsolete
-	int  debug_mode = 0;       // whether we're in debug mode
-	int32_t globalvars[MAXGLOBALVARS];  // obsolete
-	int  messagetime = 0;      // time left for auto-remove messages
-	int  usedinv = 0;          // inventory item last used
-	int  inv_top = 0, inv_numdisp = 0, obsolete_inv_numorder = 0, inv_numinline = 0;
-	int  text_speed = 0;       // how quickly text is removed
-	int  sierra_inv_color = 0; // background used to paint defualt inv window
-	int  talkanim_speed = 0;   // animation speed of talking anims
-	int  inv_item_wid = 0, inv_item_hit = 0; // set by SetInvDimensions
-	int  speech_text_shadow = 0;         // colour of outline fonts (default black)
-	int  swap_portrait_side = 0;         // sierra-style speech swap sides
-	int  speech_textwindow_gui = 0;      // textwindow used for sierra-style speech
-	int  follow_change_room_timer = 0;   // delay before moving following characters into new room
-	int  totalscore = 0;           // maximum possible score
-	int  skip_display = 0;         // how the user can skip normal Display windows
-	int  no_multiloop_repeat = 0;  // for backwards compatibility
-	int  roomscript_finished = 0;  // on_call finished in room
-	int  used_inv_on = 0;          // inv item they clicked on
-	int  no_textbg_when_voice = 0; // no textwindow bgrnd when voice speech is used
-	int  max_dialogoption_width = 0; // max width of dialog options text window
-	int  no_hicolor_fadein = 0;      // fade out but instant in for hi-color
-	int  bgspeech_game_speed = 0;    // is background speech relative to game speed
-	int  bgspeech_stay_on_display = 0; // whether to remove bg speech when DisplaySpeech is used
-	int  unfactor_speech_from_textlength = 0; // remove "&10" when calculating time for text to stay
-	int  mp3_loop_before_end = 0;    // (UNUSED!) loop this time before end of track (ms)
-	int  speech_music_drop = 0;      // how much to drop music volume by when speech is played
-	int  in_cutscene = 0;            // we are between a StartCutscene and EndCutscene
-	int  fast_forward = 0;           // player has elected to skip cutscene
-	int  room_width = 0;      // width of current room
-	int  room_height = 0;     // height of current room
+	int  score;      // player's current score
+	int  usedmode;   // set by ProcessClick to last cursor mode used
+	int  disabled_user_interface;  // >0 while in cutscene/etc
+	int  gscript_timer;    // obsolete
+	int  debug_mode;       // whether we're in debug mode
+	int  globalvars[MAXGLOBALVARS];  // obsolete
+	int  messagetime;      // time left for auto-remove messages
+	int  usedinv;          // inventory item last used
+	int  inv_top, inv_numdisp, obsolete_inv_numorder, inv_numinline;
+	int  text_speed;       // how quickly text is removed
+	int  sierra_inv_color; // background used to paint defualt inv window
+	int  talkanim_speed;   // animation speed of talking anims
+	int  inv_item_wid, inv_item_hit;  // set by SetInvDimensions
+	int  speech_text_shadow;         // colour of outline fonts (default black)
+	int  swap_portrait_side;         // sierra-style speech swap sides
+	int  speech_textwindow_gui;      // textwindow used for sierra-style speech
+	int  follow_change_room_timer;   // delay before moving following characters into new room
+	int  totalscore;           // maximum possible score
+	int  skip_display;         // how the user can skip normal Display windows
+	int  no_multiloop_repeat;  // for backwards compatibility
+	int  roomscript_finished;  // on_call finished in room
+	int  used_inv_on;          // inv item they clicked on
+	int  no_textbg_when_voice; // no textwindow bgrnd when voice speech is used
+	int  max_dialogoption_width; // max width of dialog options text window
+	int  no_hicolor_fadein;      // fade out but instant in for hi-color
+	int  bgspeech_game_speed;    // is background speech relative to game speed
+	int  bgspeech_stay_on_display; // whether to remove bg speech when DisplaySpeech is used
+	int  unfactor_speech_from_textlength; // remove "&10" when calculating time for text to stay
+	int  mp3_loop_before_end;    // (UNUSED!) loop this time before end of track (ms)
+	int  speech_music_drop;      // how much to drop music volume by when speech is played
+	int  in_cutscene;            // we are between a StartCutscene and EndCutscene
+	int  fast_forward;           // player has elected to skip cutscene
+	int  room_width;      // width of current room
+	int  room_height;     // height of current room
 	// ** up to here is referenced in the plugin interface
-	int  game_speed_modifier = 0;
-	int  score_sound = 0;
-	int  takeover_data = 0;  // value passed to RunAGSGame in previous game
-	int  replay_hotkey_unused = 0;  // (UNUSED!) StartRecording: not supported
-	int  dialog_options_x = 0;
-	int  dialog_options_y = 0;
-	int  narrator_speech = 0;
-	int  ambient_sounds_persist = 0;
-	int  lipsync_speed = 0;
-	int  close_mouth_speech_time = 0; // stop speech animation at (messagetime - close_mouth_speech_time)
+	int  game_speed_modifier;
+	int  score_sound;
+	int  takeover_data;  // value passed to RunAGSGame in previous game
+	int  replay_hotkey_unused;  // (UNUSED!) StartRecording: not supported
+	int  dialog_options_x;
+	int  dialog_options_y;
+	int  narrator_speech;
+	int  ambient_sounds_persist;
+	int  lipsync_speed;
+	int  close_mouth_speech_time; // stop speech animation at (messagetime - close_mouth_speech_time)
 	// (this is designed to work in text-only mode)
-	int  disable_antialiasing = 0;
-	int  text_speed_modifier = 0;
-	HorAlignment text_align = kHAlignNone;
-	int  speech_bubble_width = 0;
-	int  min_dialogoption_width = 0;
-	int  disable_dialog_parser = 0;
-	int  anim_background_speed = 0;  // the setting for this room
-	int  top_bar_backcolor = 0;
-	int  top_bar_textcolor = 0;
-	int  top_bar_bordercolor = 0;
-	int  top_bar_borderwidth = 0;
-	int  top_bar_ypos = 0;
-	int  screenshot_width = 0;
-	int  screenshot_height = 0;
-	int  top_bar_font = 0;
-	HorAlignment speech_text_align = kHAlignNone;
-	int  auto_use_walkto_points = 0;
-	int  inventory_greys_out = 0;
-	int  skip_speech_specific_key = 0;
-	int  abort_key = 0;
-	int  fade_to_red = 0;
-	int  fade_to_green = 0;
-	int  fade_to_blue = 0;
-	int  show_single_dialog_option = 0;
-	int  keep_screen_during_instant_transition = 0;
-	int  read_dialog_option_colour = 0;
-	int  stop_dialog_at_end = 0;
-	int  speech_portrait_placement = 0; // speech portrait placement mode (automatic/custom)
-	int  speech_portrait_x = 0; // a speech portrait x offset from corresponding screen side
-	int  speech_portrait_y = 0; // a speech portrait y offset
-	int  speech_display_post_time_ms = 0; // keep speech text/portrait on screen after text/voice has finished playing = 0;
+	int  disable_antialiasing;
+	int  text_speed_modifier;
+	HorAlignment text_align;
+	int  speech_bubble_width;
+	int  min_dialogoption_width;
+	int  disable_dialog_parser;
+	int  anim_background_speed;  // the setting for this room
+	int  top_bar_backcolor;
+	int  top_bar_textcolor;
+	int  top_bar_bordercolor;
+	int  top_bar_borderwidth;
+	int  top_bar_ypos;
+	int  screenshot_width;
+	int  screenshot_height;
+	int  top_bar_font;
+	HorAlignment speech_text_align;
+	int  auto_use_walkto_points;
+	int  inventory_greys_out;
+	int  skip_speech_specific_key;
+	int  abort_key;
+	int  fade_to_red;
+	int  fade_to_green;
+	int  fade_to_blue;
+	int  show_single_dialog_option;
+	int  keep_screen_during_instant_transition;
+	int  read_dialog_option_colour;
+	int  stop_dialog_at_end;
+	int  speech_portrait_placement; // speech portrait placement mode (automatic/custom)
+	int  speech_portrait_x; // a speech portrait x offset from corresponding screen side
+	int  speech_portrait_y; // a speech portrait y offset
+	int  speech_display_post_time_ms; // keep speech text/portrait on screen after text/voice has finished playing;
 	// no speech animation is supposed to be played at this time
-	int  dialog_options_highlight_color = 0; // The colour used for highlighted (hovered over) text in dialog options
-	int32_t reserved[GAME_STATE_RESERVED_INTS];  // make sure if a future version adds a var, it doesn't mess anything up
-	// ** up to here is referenced in the script "_GP(game)." object
-	long  randseed = 0;    // random seed
-	int   player_on_region = 0;    // player's current region
-	int   screen_is_faded_out = 0; // the screen is currently black
-	int   check_interaction_only = 0;
-	int   bg_frame = 0, bg_anim_delay = 0; // for animating backgrounds
-	int   music_vol_was = 0;  // before the volume drop
-	short wait_counter = 0;
-	char  wait_skipped_by = 0; // tells how last wait was skipped [not serialized]
-	int   wait_skipped_by_data = 0; // extended data telling how last wait was skipped [not serialized]
-	short mboundx1 = 0, mboundx2 = 0, mboundy1 = 0, mboundy2 = 0;
-	int   fade_effect = 0;
-	int   bg_frame_locked = 0;
-	int32_t globalscriptvars[MAXGSVALUES];
-	int   cur_music_number = 0, music_repeat = 0;
-	int   music_master_volume = 0;
-	int   digital_master_volume = 0;
+	int  dialog_options_highlight_color; // The colour used for highlighted (hovered over) text in dialog options
+	int  reserved[GAME_STATE_RESERVED_INTS];  // make sure if a future version adds a var, it doesn't mess anything up
+	// ** up to here is referenced in the script "game." object
+	long  randseed;    // random seed
+	int   player_on_region;    // player's current region
+	int   screen_is_faded_out; // the screen is currently black
+	int   check_interaction_only;
+	int   bg_frame, bg_anim_delay;  // for animating backgrounds
+	int   music_vol_was;  // before the volume drop
+	short wait_counter;
+	short mboundx1, mboundx2, mboundy1, mboundy2;
+	int   fade_effect;
+	int   bg_frame_locked;
+	int   globalscriptvars[MAXGSVALUES];
+	int   cur_music_number, music_repeat;
+	int   music_master_volume;
+	int   digital_master_volume;
 	char  walkable_areas_on[MAX_WALK_AREAS + 1];
-	short screen_flipped = 0;
-	int   entered_at_x = 0, entered_at_y = 0, entered_edge = 0;
-	int   want_speech = 0;
-	int   cant_skip_speech = 0;
-	int32_t script_timers[MAX_TIMERS];
-	int   sound_volume = 0, speech_volume = 0;
-	int   normal_font = 0, speech_font = 0;
-	char  key_skip_wait = 0;
-	int   swap_portrait_lastchar = 0;
-	int   swap_portrait_lastlastchar = 0;
-	int   separate_music_lib = 0;
-	int   in_conversation = 0;
-	int   screen_tint = 0;
-	int   num_parsed_words = 0;
+	short screen_flipped;
+	int   entered_at_x, entered_at_y, entered_edge;
+	int   want_speech;
+	int   cant_skip_speech;
+	int   script_timers[MAX_TIMERS];
+	int   sound_volume, speech_volume;
+	int   normal_font, speech_font;
+	char  key_skip_wait;
+	int   swap_portrait_lastchar;
+	int   swap_portrait_lastlastchar;
+	int   separate_music_lib;
+	int   in_conversation;
+	int   screen_tint;
+	int   num_parsed_words;
 	short parsed_words[MAX_PARSED_WORDS];
 	char  bad_parsed_word[100];
-	int   raw_color = 0;
-	int32_t raw_modified[MAX_ROOM_BGFRAMES];
-	Shared::PBitmap raw_drawing_surface = nullptr;
+	int   raw_color;
+	int   raw_modified[MAX_ROOM_BGFRAMES];
+	Shared::PBitmap raw_drawing_surface;
 	short filenumbers[MAXSAVEGAMES];
-	int   room_changes = 0;
-	int   mouse_cursor_hidden = 0;
-	int   silent_midi = 0;
-	int   silent_midi_channel = 0;
-	int   current_music_repeating = 0;  // remember what the loop flag was when this music started
-	unsigned long shakesc_delay = 0;  // unsigned long to match _G(loopcounter)
-	int   shakesc_amount = 0, shakesc_length = 0;
-	int   rtint_red = 0, rtint_green = 0, rtint_blue = 0, rtint_level = 0, rtint_light = 0;
-	bool  rtint_enabled = 0;
-	int   end_cutscene_music = 0;
-	int   skip_until_char_stops = 0;
-	int   get_loc_name_last_time = 0;
-	int   get_loc_name_save_cursor = 0;
-	int   restore_cursor_mode_to = 0;
-	int   restore_cursor_image_to = 0;
-	short music_queue_size = 0;
+	int   room_changes;
+	int   mouse_cursor_hidden;
+	int   silent_midi;
+	int   silent_midi_channel;
+	int   current_music_repeating;  // remember what the loop flag was when this music started
+	unsigned long shakesc_delay;  // unsigned long to match _G(loopcounter)
+	int   shakesc_amount, shakesc_length;
+	int   rtint_red, rtint_green, rtint_blue, rtint_level, rtint_light;
+	bool  rtint_enabled;
+	int   end_cutscene_music;
+	int   skip_until_char_stops;
+	int   get_loc_name_last_time;
+	int   get_loc_name_save_cursor;
+	int   restore_cursor_mode_to;
+	int   restore_cursor_image_to;
+	short music_queue_size;
 	short music_queue[MAX_QUEUED_MUSIC];
-	short new_music_queue_size = 0;
-	short crossfading_out_channel = 0;
-	short crossfade_step = 0;
-	short crossfade_out_volume_per_step = 0;
-	short crossfade_initial_volume_out = 0;
-	short crossfading_in_channel = 0;
-	short crossfade_in_volume_per_step = 0;
-	short crossfade_final_volume_in = 0;
+	short new_music_queue_size;
+	short crossfading_out_channel;
+	short crossfade_step;
+	short crossfade_out_volume_per_step;
+	short crossfade_initial_volume_out;
+	short crossfading_in_channel;
+	short crossfade_in_volume_per_step;
+	short crossfade_final_volume_in;
 	QueuedAudioItem new_music_queue[MAX_QUEUED_MUSIC];
 	char  takeover_from[50];
 	char  playmp3file_name[PLAYMP3FILE_MAX_FILENAME_LEN];
 	char  globalstrings[MAXGLOBALSTRINGS][MAX_MAXSTRLEN];
 	char  lastParserEntry[MAX_MAXSTRLEN];
 	char  game_name[100];
-	int   ground_level_areas_disabled = 0;
-	int   next_screen_transition = 0;
-	int   gamma_adjustment = 0;
-	short temporarily_turned_off_character = 0;  // Hide Player Charactr ticked
-	short inv_backwards_compatibility = 0;
-	int32_t *gui_draw_order = nullptr;
+	int   ground_level_areas_disabled;
+	int   next_screen_transition;
+	int   gamma_adjustment;
+	short temporarily_turned_off_character;  // Hide Player Charactr ticked
+	short inv_backwards_compatibility;
+	int *gui_draw_order;
 	std::vector<AGS::Shared::String> do_once_tokens;
-	int   text_min_display_time_ms = 0;
-	int   ignore_user_input_after_text_timeout_ms = 0;
-	int32_t   default_audio_type_volumes[MAX_AUDIO_TYPES];
+	int   text_min_display_time_ms;
+	int   ignore_user_input_after_text_timeout_ms;
+	int   default_audio_type_volumes[MAX_AUDIO_TYPES];
 
 	// Dynamic custom property values for characters and items
 	std::vector<AGS::Shared::StringIMap> charProps;
@@ -235,16 +234,16 @@ struct GameState {
 	// Dynamic speech state
 	//
 	// Tells whether there is a voice-over played during current speech
-	bool  speech_has_voice = 0;
-	// Tells whether the voice was played in blocking mode = 0;
+	bool  speech_has_voice;
+	// Tells whether the voice was played in blocking mode;
 	// atm blocking speech handles itself, and we only need to finalize
-	// non-blocking voice speech during game update = 0; speech refactor would be
+	// non-blocking voice speech during game update; speech refactor would be
 	// required to get rid of this rule.
-	bool  speech_voice_blocking = 0;
+	bool  speech_voice_blocking;
 	// Tells whether character speech stays on screen not animated for additional time
-	bool  speech_in_post_state = 0;
+	bool  speech_in_post_state;
 
-	int shake_screen_yoff = 0; // y offset of the shaking screen
+	int shake_screen_yoff; // y offset of the shaking screen
 
 
 	GameState();
@@ -366,7 +365,7 @@ private:
 	void UpdateRoomCamera(int index);
 
 	// Defines if the room viewport should be adjusted to the room size automatically.
-	bool _isAutoRoomViewport = true;
+	bool _isAutoRoomViewport;
 	// Main viewport defines the rectangle of the drawn and interactable area
 	// in the most basic case it will be equal to the game size.
 	Viewport _mainViewport;
@@ -386,11 +385,11 @@ private:
 	std::vector<std::pair<ScriptCamera *, int32_t>> _scCameraRefs;
 
 	// Tells that the main viewport's position has changed since last game update
-	bool  _mainViewportHasChanged = false;
+	bool  _mainViewportHasChanged;
 	// Tells that room viewports need z-order resort
-	bool  _roomViewportZOrderChanged = false;
+	bool  _roomViewportZOrderChanged;
 
-	AGS_Clock::time_point _ignoreUserInputUntilTime = 0;
+	AGS_Clock::time_point _ignoreUserInputUntilTime;
 };
 
 // Converts legacy alignment type used in script API
diff --git a/engines/ags/engine/ac/global_api.cpp b/engines/ags/engine/ac/global_api.cpp
index 817bdfcfc2..1d74109bca 100644
--- a/engines/ags/engine/ac/global_api.cpp
+++ b/engines/ags/engine/ac/global_api.cpp
@@ -29,26 +29,27 @@
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
-#include "ags/engine/ac/cdaudio.h"
+
+#include "ags/engine/ac/cd_audio.h"
 #include "ags/engine/ac/display.h"
-#include "ags/engine/ac/dynamicsprite.h"
+#include "ags/engine/ac/dynamic_sprite.h"
 #include "ags/engine/ac/event.h"
 #include "ags/engine/ac/game.h"
 #include "ags/engine/ac/global_audio.h"
 #include "ags/engine/ac/global_button.h"
 #include "ags/engine/ac/global_character.h"
-#include "ags/engine/ac/global_datetime.h"
+#include "ags/engine/ac/global_date_time.h"
 #include "ags/engine/ac/global_debug.h"
 #include "ags/engine/ac/global_dialog.h"
 #include "ags/engine/ac/global_display.h"
-#include "ags/engine/ac/global_drawingsurface.h"
-#include "ags/engine/ac/global_dynamicsprite.h"
+#include "ags/engine/ac/global_drawing_surface.h"
+#include "ags/engine/ac/global_dynamic_sprite.h"
 #include "ags/engine/ac/global_file.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/global_gui.h"
 #include "ags/engine/ac/global_hotspot.h"
-#include "ags/engine/ac/global_inventoryitem.h"
-#include "ags/engine/ac/global_invwindow.h"
+#include "ags/engine/ac/global_inventory_item.h"
+#include "ags/engine/ac/global_inv_window.h"
 #include "ags/engine/ac/global_label.h"
 #include "ags/engine/ac/global_listbox.h"
 #include "ags/engine/ac/global_mouse.h"
@@ -66,10 +67,10 @@
 #include "ags/engine/ac/global_timer.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/global_video.h"
-#include "ags/engine/ac/global_viewframe.h"
+#include "ags/engine/ac/global_view_frame.h"
 #include "ags/engine/ac/global_viewport.h"
-#include "ags/engine/ac/global_walkablearea.h"
-#include "ags/engine/ac/global_walkbehind.h"
+#include "ags/engine/ac/global_walkable_area.h"
+#include "ags/engine/ac/global_walk_behind.h"
 #include "ags/engine/ac/math.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/ac/parser.h"
@@ -78,11 +79,13 @@
 #include "ags/engine/media/video/video.h"
 #include "ags/shared/util/string_compat.h"
 #include "ags/engine/media/audio/audio_system.h"
-#include "ags/engine/ac/dynobj/scriptstring.h"
+#include "ags/engine/ac/dynobj/script_string.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
 
+
+
 // void (char*texx, ...)
 RuntimeScriptValue Sc_sc_AbortGame(const RuntimeScriptValue *params, int32_t param_count) {
 	API_SCALL_SCRIPT_SPRINTF(_sc_AbortGame, 1);
@@ -543,7 +546,7 @@ RuntimeScriptValue Sc_GetInvGraphic(const RuntimeScriptValue *params, int32_t pa
 	API_SCALL_INT_PINT(GetInvGraphic);
 }
 
-// void (int indx,char*buff)
+// void (int indx,char*_G(buff))
 RuntimeScriptValue Sc_GetInvName(const RuntimeScriptValue *params, int32_t param_count) {
 	API_SCALL_VOID_PINT_POBJ(GetInvName, char);
 }
@@ -715,16 +718,6 @@ RuntimeScriptValue Sc_GetWalkableAreaAtScreen(const RuntimeScriptValue *params,
 	API_SCALL_INT_PINT2(GetWalkableAreaAtScreen);
 }
 
-RuntimeScriptValue Sc_GetDrawingSurfaceForWalkableArea(const RuntimeScriptValue *params, int32_t param_count) {
-	ScriptDrawingSurface *ret_obj = Room_GetDrawingSurfaceForMask(kRoomAreaWalkable);
-	return RuntimeScriptValue().SetDynamicObject(ret_obj, ret_obj);
-}
-
-RuntimeScriptValue Sc_GetDrawingSurfaceForWalkbehind(const RuntimeScriptValue *params, int32_t param_count) {
-	ScriptDrawingSurface *ret_obj = Room_GetDrawingSurfaceForMask(kRoomAreaWalkBehind);
-	return RuntimeScriptValue().SetDynamicObject(ret_obj, ret_obj);
-}
-
 // void (int amnt)
 RuntimeScriptValue Sc_GiveScore(const RuntimeScriptValue *params, int32_t param_count) {
 	API_SCALL_VOID_PINT(GiveScore);
@@ -1869,19 +1862,11 @@ RuntimeScriptValue Sc_WaitKey(const RuntimeScriptValue *params, int32_t param_co
 	API_SCALL_INT_PINT(WaitKey);
 }
 
-RuntimeScriptValue Sc_WaitMouse(const RuntimeScriptValue *params, int32_t param_count) {
-	API_SCALL_INT_PINT(WaitMouse);
-}
-
 // int (int nloops)
 RuntimeScriptValue Sc_WaitMouseKey(const RuntimeScriptValue *params, int32_t param_count) {
 	API_SCALL_INT_PINT(WaitMouseKey);
 }
 
-RuntimeScriptValue Sc_SkipWait(const RuntimeScriptValue *params, int32_t param_count) {
-	API_SCALL_VOID(SkipWait);
-}
-
 //=============================================================================
 //
 // Exclusive API for Plugins
@@ -2082,8 +2067,6 @@ void RegisterGlobalAPI() {
 	ccAddExternalStaticFunction("GetWalkableAreaAtRoom",    Sc_GetWalkableAreaAtRoom);
 	ccAddExternalStaticFunction("GetWalkableAreaAt",        Sc_GetWalkableAreaAtScreen);
 	ccAddExternalStaticFunction("GetWalkableAreaAtScreen",  Sc_GetWalkableAreaAtScreen);
-	ccAddExternalStaticFunction("GetDrawingSurfaceForWalkableArea", Sc_GetDrawingSurfaceForWalkableArea);
-	ccAddExternalStaticFunction("GetDrawingSurfaceForWalkbehind", Sc_GetDrawingSurfaceForWalkbehind);
 	ccAddExternalStaticFunction("GiveScore",                Sc_GiveScore);
 	ccAddExternalStaticFunction("HasPlayerBeenInRoom",      Sc_HasPlayerBeenInRoom);
 	ccAddExternalStaticFunction("HideMouseCursor",          Sc_HideMouseCursor);
@@ -2319,9 +2302,7 @@ void RegisterGlobalAPI() {
 	ccAddExternalStaticFunction("UpdatePalette",            Sc_UpdatePalette);
 	ccAddExternalStaticFunction("Wait",                     Sc_scrWait);
 	ccAddExternalStaticFunction("WaitKey",                  Sc_WaitKey);
-	ccAddExternalStaticFunction("WaitMouse",                Sc_WaitMouse);
 	ccAddExternalStaticFunction("WaitMouseKey",             Sc_WaitMouseKey);
-	ccAddExternalStaticFunction("SkipWait",                 Sc_SkipWait);
 
 	/* ----------------------- Registering unsafe exports for plugins -----------------------*/
 
diff --git a/engines/ags/engine/ac/global_audio.cpp b/engines/ags/engine/ac/global_audio.cpp
index 8e3bc2f788..39a1c0dd44 100644
--- a/engines/ags/engine/ac/global_audio.cpp
+++ b/engines/ags/engine/ac/global_audio.cpp
@@ -22,20 +22,19 @@
 
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/game.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_audio.h"
-#include "ags/engine/ac/lipsync.h"
+#include "ags/engine/ac/lip_sync.h"
 #include "ags/engine/ac/path_helper.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/engine/debugging/debugger.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/engine/main/engine.h"
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/engine/ac/timer.h"
 #include "ags/shared/util/string_compat.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
@@ -65,7 +64,7 @@ void PlayAmbientSound(int channel, int sndnum, int vol, int x, int y) {
 
 	// only play the sound if it's not already playing
 	if ((_GP(ambient)[channel].channel < 1) || (!channel_is_playing(_GP(ambient)[channel].channel)) ||
-		(_GP(ambient)[channel].num != sndnum)) {
+	        (_GP(ambient)[channel].num != sndnum)) {
 
 		StopAmbientSound(channel);
 		// in case a normal non-ambient sound was playing, stop it too
@@ -210,8 +209,7 @@ int IsMusicPlaying() {
 
 	AudioChannelsLock lock;
 	auto *ch = lock.GetChannel(SCHAN_MUSIC);
-	if (ch == nullptr) {
-		// This was probably a hacky fix in case it was not reset by game update; TODO: find out if needed
+	if (ch == nullptr) { // This was probably a hacky fix in case it was not reset by game update; TODO: find out if needed
 		_G(current_music_type) = 0;
 		return 0;
 	}
@@ -237,7 +235,7 @@ int PlayMusicQueued(int musnum) {
 	}
 
 	if ((_GP(play).music_queue_size > 0) &&
-		(_GP(play).music_queue[_GP(play).music_queue_size - 1] >= QUEUED_MUSIC_REPEAT)) {
+	        (_GP(play).music_queue[_GP(play).music_queue_size - 1] >= QUEUED_MUSIC_REPEAT)) {
 		debug_script_warn("PlayMusicQueued: cannot queue music after a repeating tune has been queued");
 		return 0;
 	}
@@ -321,7 +319,7 @@ void SetMusicVolume(int newvol) {
 
 void SetMusicMasterVolume(int newvol) {
 	const int min_volume = _G(loaded_game_file_version) < kGameVersion_330 ? 0 :
-		-LegacyMusicMasterVolumeAdjustment - (kRoomVolumeMax * LegacyRoomVolumeFactor);
+	                       -LegacyMusicMasterVolumeAdjustment - (kRoomVolumeMax * LegacyRoomVolumeFactor);
 	if ((newvol < min_volume) | (newvol > 100))
 		quitprintf("!SetMusicMasterVolume: invalid volume - must be from %d to %d", min_volume, 100);
 	_GP(play).music_master_volume = newvol + LegacyMusicMasterVolumeAdjustment;
@@ -379,7 +377,7 @@ void PlayMP3File(const char *filename) {
 
 	debug_script_log("PlayMP3File %s", filename);
 
-	AssetPath asset_name("", filename);
+	AssetPath asset_name(filename, "audio");
 
 	int useChan = prepare_for_new_music();
 	bool doLoop = (_GP(play).music_repeat > 0);
@@ -498,6 +496,8 @@ int IsMusicVoxAvailable() {
 	return _GP(play).separate_music_lib;
 }
 
+
+
 ScriptAudioChannel *PlayVoiceClip(CharacterInfo *ch, int sndid, bool as_speech) {
 	if (!play_voice_nonblocking(ch->index_id, sndid, as_speech))
 		return NULL;
@@ -539,13 +539,9 @@ static bool play_voice_clip_on_channel(const String &voice_name) {
 	}
 
 	if (speechmp3 != nullptr) {
-		SoundClipWaveBase *clip = dynamic_cast<SoundClipWaveBase *>(speechmp3);
-		if (clip)
-			clip->_soundType = Audio::Mixer::kSpeechSoundType;
-
 		if (!speechmp3->play()) {
 			// not assigned to a channel, so clean up manually.
-			//speechmp3->destroy();
+			speechmp3->destroy();
 			delete speechmp3;
 			speechmp3 = nullptr;
 		}
diff --git a/engines/ags/engine/ac/global_audio.h b/engines/ags/engine/ac/global_audio.h
index 4c14d539f5..a1f3d0254a 100644
--- a/engines/ags/engine/ac/global_audio.h
+++ b/engines/ags/engine/ac/global_audio.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBALAUDIO_H
-#define AGS_ENGINE_AC_GLOBALAUDIO_H
+#ifndef AGS_ENGINE_AC_GLOBAL_AUDIO_H
+#define AGS_ENGINE_AC_GLOBAL_AUDIO_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_button.cpp b/engines/ags/engine/ac/global_button.cpp
index f44f9a2093..a5a1ebb876 100644
--- a/engines/ags/engine/ac/global_button.cpp
+++ b/engines/ags/engine/ac/global_button.cpp
@@ -23,16 +23,17 @@
 #include "ags/engine/ac/global_button.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/button.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/string.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/shared/gui/guibutton.h"
-#include "ags/globals.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/shared/gui/gui_button.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
+
+
 void SetButtonText(int guin, int objn, const char *newtx) {
 	VALIDATE_STRING(newtx);
 	if ((guin < 0) | (guin >= _GP(game).numgui))
@@ -80,6 +81,8 @@ int GetButtonPic(int guin, int objn, int ptype) {
 	} else { // pushed pic
 		return guil->PushedImage;
 	}
+
+	quit("internal error in getbuttonpic");
 }
 
 void SetButtonPic(int guin, int objn, int ptype, int slotn) {
diff --git a/engines/ags/engine/ac/global_button.h b/engines/ags/engine/ac/global_button.h
index dbda062063..f8dfefcbac 100644
--- a/engines/ags/engine/ac/global_button.h
+++ b/engines/ags/engine/ac/global_button.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBALBUTTON_H
-#define AGS_ENGINE_AC_GLOBALBUTTON_H
+#ifndef AGS_ENGINE_AC_GLOBAL_BUTTON_H
+#define AGS_ENGINE_AC_GLOBAL_BUTTON_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_character.cpp b/engines/ags/engine/ac/global_character.cpp
index b0129df56a..4ca5965849 100644
--- a/engines/ags/engine/ac/global_character.cpp
+++ b/engines/ags/engine/ac/global_character.cpp
@@ -33,25 +33,39 @@
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/event.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_overlay.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/object.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/properties.h"
-#include "ags/engine/ac/screenoverlay.h"
+#include "ags/engine/ac/screen_overlay.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/engine/main/game_run.h"
 #include "ags/engine/script/script.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
+
+
+
+
+
+
+
+
+// defined in character unit
+
+
+
+
+
+
 void StopMoving(int chaa) {
 
 	Character_StopMoving(&_GP(game).chars[chaa]);
@@ -102,8 +116,8 @@ int GetCharacterWidth(int ww) {
 
 	if (_G(charextra)[ww].width < 1) {
 		if ((char1->view < 0) ||
-			(char1->loop >= _G(views)[char1->view].numLoops) ||
-			(char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
+		        (char1->loop >= _G(views)[char1->view].numLoops) ||
+		        (char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
 			debug_script_warn("GetCharacterWidth: Character %s has invalid frame: view %d, loop %d, frame %d", char1->scrname, char1->view + 1, char1->loop, char1->frame);
 			return data_to_game_coord(4);
 		}
@@ -118,8 +132,8 @@ int GetCharacterHeight(int charid) {
 
 	if (_G(charextra)[charid].height < 1) {
 		if ((char1->view < 0) ||
-			(char1->loop >= _G(views)[char1->view].numLoops) ||
-			(char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
+		        (char1->loop >= _G(views)[char1->view].numLoops) ||
+		        (char1->frame >= _G(views)[char1->view].loops[char1->loop].numFrames)) {
 			debug_script_warn("GetCharacterHeight: Character %s has invalid frame: view %d, loop %d, frame %d", char1->scrname, char1->view + 1, char1->loop, char1->frame);
 			return data_to_game_coord(2);
 		}
@@ -391,7 +405,7 @@ void RunCharacterInteraction(int cc, int mood) {
 	} else {
 		if (passon >= 0)
 			run_interaction_event(_GP(game).intrChar[cc].get(), passon, 4, (passon == 3));
-		run_interaction_event(_GP(game).intrChar[cc].get(), 4); // any click on char
+		run_interaction_event(_GP(game).intrChar[cc].get(), 4);  // any click on char
 	}
 }
 
@@ -470,8 +484,7 @@ void update_invorder() {
 	}
 	// backwards compatibility
 	_GP(play).obsolete_inv_numorder = _G(charextra)[_GP(game).playercharacter].invorder_count;
-
-	_G(guis_need_update) = 1;
+	GUI::MarkInventoryForUpdate(_GP(game).playercharacter, true);
 }
 
 void add_inventory(int inum) {
@@ -534,15 +547,16 @@ void DisplaySpeechAt(int xx, int yy, int wii, int aschar, const char *spch) {
 
 int DisplaySpeechBackground(int charid, const char *speel) {
 	// remove any previous background speech for this character
-	for (size_t i = 0; i < _GP(screenover).size();) {
-		if (_GP(screenover)[i].bgSpeechForChar == charid)
-			remove_screen_overlay_index(i);
-		else
-			i++;
+	int cc;
+	for (cc = 0; cc < _G(numscreenover); cc++) {
+		if (_GP(screenover)[cc].bgSpeechForChar == charid) {
+			remove_screen_overlay_index(cc);
+			cc--;
+		}
 	}
 
 	int ovrl = CreateTextOverlay(OVR_AUTOPLACE, charid, _GP(play).GetUIViewport().GetWidth() / 2, FONT_SPEECH,
-		-_GP(game).chars[charid].talkcolor, get_translation(speel), DISPLAYTEXT_NORMALOVERLAY);
+	                             -_GP(game).chars[charid].talkcolor, get_translation(speel), DISPLAYTEXT_NORMALOVERLAY);
 
 	int scid = find_overlay_of_type(ovrl);
 	_GP(screenover)[scid].bgSpeechForChar = charid;
diff --git a/engines/ags/engine/ac/global_character.h b/engines/ags/engine/ac/global_character.h
index 6745d410b5..b015b55037 100644
--- a/engines/ags/engine/ac/global_character.h
+++ b/engines/ags/engine/ac/global_character.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBALCHARACTER_H
-#define AGS_ENGINE_AC_GLOBALCHARACTER_H
+#ifndef AGS_ENGINE_AC_GLOBAL_CHARACTER_H
+#define AGS_ENGINE_AC_GLOBAL_CHARACTER_H
 
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/shared/ac/character_info.h"
 
 namespace AGS3 {
 
@@ -91,6 +91,6 @@ void __sc_displayspeech(int chid, const char *text);
 void DisplaySpeechAt(int xx, int yy, int wii, int aschar, const char *spch);
 int DisplaySpeechBackground(int charid, const char *speel);
 
-} // nemspace AGS3
+} // namespace AGS3
 
 #endif
diff --git a/engines/ags/engine/ac/global_datetime.cpp b/engines/ags/engine/ac/global_date_time.cpp
similarity index 93%
rename from engines/ags/engine/ac/global_datetime.cpp
rename to engines/ags/engine/ac/global_date_time.cpp
index 585feb3a23..40d950322b 100644
--- a/engines/ags/engine/ac/global_datetime.cpp
+++ b/engines/ags/engine/ac/global_date_time.cpp
@@ -20,8 +20,9 @@
  *
  */
 
-#include "ags/engine/ac/global_datetime.h"
-#include "ags/engine/ac/datetime.h"
+//include <time.h>
+#include "ags/engine/ac/global_date_time.h"
+#include "ags/engine/ac/date_time.h"
 #include "ags/shared/ac/common.h"
 #include "common/system.h"
 
diff --git a/engines/ags/engine/ac/global_datetime.h b/engines/ags/engine/ac/global_date_time.h
similarity index 94%
rename from engines/ags/engine/ac/global_datetime.h
rename to engines/ags/engine/ac/global_date_time.h
index 4fdfce993a..6edcbe2307 100644
--- a/engines/ags/engine/ac/global_datetime.h
+++ b/engines/ags/engine/ac/global_date_time.h
@@ -25,8 +25,8 @@
 
 namespace AGS3 {
 
-extern int sc_GetTime(int whatti);
-extern int GetRawTime();
+int sc_GetTime(int whatti);
+int GetRawTime();
 
 } // namespace AGS3
 
diff --git a/engines/ags/engine/ac/global_debug.cpp b/engines/ags/engine/ac/global_debug.cpp
index 85431636a9..71b4c9197c 100644
--- a/engines/ags/engine/ac/global_debug.cpp
+++ b/engines/ags/engine/ac/global_debug.cpp
@@ -22,31 +22,31 @@
 
 #include "ags/engine/ac/global_debug.h"
 #include "ags/shared/ac/common.h"
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/game.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_display.h"
 #include "ags/engine/ac/global_room.h"
-#include "ags/engine/ac/movelist.h"
+#include "ags/engine/ac/move_list.h"
 #include "ags/engine/ac/properties.h"
 #include "ags/engine/ac/sys_events.h"
+#include "ags/engine/ac/translation.h"
 #include "ags/engine/ac/tree_map.h"
-#include "ags/engine/ac/walkablearea.h"
+#include "ags/engine/ac/walkable_area.h"
 #include "ags/engine/gfx/gfxfilter.h"
-#include "ags/engine/gui/guidialog.h"
+#include "ags/engine/gui/gui_dialog.h"
 #include "ags/shared/script/cc_options.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/engine/debugging/debugger.h"
 #include "ags/engine/main/main.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/shared/gfx/bitmap.h"
-#include "ags/engine/gfx/graphicsdriver.h"
+#include "ags/engine/gfx/graphics_driver.h"
 #include "ags/engine/main/graphics_mode.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
@@ -58,23 +58,23 @@ String GetRuntimeInfo() {
 	Rect render_frame = _G(gfxDriver)->GetRenderDestination();
 	PGfxFilter filter = _G(gfxDriver)->GetGraphicsFilter();
 	String runtimeInfo = String::FromFormat(
-		"Adventure Game Studio run-time engine[ACI version %s"
-		"[Game resolution %d x %d (%d-bit)"
-		"[Running %d x %d at %d-bit%s%s[GFX: %s; %s[Draw frame %d x %d["
-		"Sprite cache size: %d KB (limit %d KB; %d locked)",
-		_G(EngineVersion).LongString.GetCStr(), _GP(game).GetGameRes().Width, _GP(game).GetGameRes().Height, _GP(game).GetColorDepth(),
-		mode.Width, mode.Height, mode.ColorDepth, (_G(convert_16bit_bgr)) ? " BGR" : "",
-		mode.Windowed ? " W" : "",
-		_G(gfxDriver)->GetDriverName(), filter->GetInfo().Name.GetCStr(),
-		render_frame.GetWidth(), render_frame.GetHeight(),
-		_GP(spriteset).GetCacheSize() / 1024, _GP(spriteset).GetMaxCacheSize() / 1024, _GP(spriteset).GetLockedSize() / 1024);
+	                         "Adventure Game Studio run-time engine[ACI version %s"
+	                         "[Game resolution %d x %d (%d-bit)"
+	                         "[Running %d x %d at %d-bit%s%s[GFX: %s; %s[Draw frame %d x %d["
+	                         "Sprite cache size: %d KB (limit %d KB; %d locked)",
+	                         _G(EngineVersion).LongString.GetCStr(), _GP(game).GetGameRes().Width, _GP(game).GetGameRes().Height, _GP(game).GetColorDepth(),
+	                         mode.Width, mode.Height, mode.ColorDepth, (_G(convert_16bit_bgr)) ? " BGR" : "",
+	                         mode.Windowed ? " W" : "",
+	                         _G(gfxDriver)->GetDriverName(), filter->GetInfo().Name.GetCStr(),
+	                         render_frame.GetWidth(), render_frame.GetHeight(),
+	                         _GP(spriteset).GetCacheSize() / 1024, _GP(spriteset).GetMaxCacheSize() / 1024, _GP(spriteset).GetLockedSize() / 1024);
 	if (_GP(play).separate_music_lib)
 		runtimeInfo.Append("[AUDIO.VOX enabled");
 	if (_GP(play).want_speech >= 1)
 		runtimeInfo.Append("[SPEECH.VOX enabled");
-	if (_G(transtree) != nullptr) {
+	if (get_translation_tree() != nullptr) {
 		runtimeInfo.Append("[Using translation ");
-		runtimeInfo.Append(_G(transFileName));
+		runtimeInfo.Append(get_translation_name());
 	}
 
 	return runtimeInfo;
@@ -94,8 +94,7 @@ void script_debug(int cmdd, int dataa) {
 		//    Display("shftR: %d  shftG: %d  shftB: %d", _G(_rgb_r_shift_16), _G(_rgb_g_shift_16), _G(_rgb_b_shift_16));
 		//    Display("Remaining memory: %d kb",_go32_dpmi_remaining_virtual_memory()/1024);
 		//Display("Play char bcd: %d",->GetColorDepth(_GP(spriteset)[_G(views)[_G(playerchar)->view].frames[_G(playerchar)->loop][_G(playerchar)->frame].pic]));
-	} else if (cmdd == 2) {
-		// show walkable areas from here
+	} else if (cmdd == 2) {  // show walkable areas from here
 		// TODO: support multiple viewports?!
 		const int viewport_index = 0;
 		const int camera_index = 0;
diff --git a/engines/ags/engine/ac/global_debug.h b/engines/ags/engine/ac/global_debug.h
index f104c53fcc..547e6ae5f3 100644
--- a/engines/ags/engine/ac/global_debug.h
+++ b/engines/ags/engine/ac/global_debug.h
@@ -20,9 +20,10 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBALDEBUG_H
-#define AGS_ENGINE_AC_GLOBALDEBUG_H
+#ifndef AGS_ENGINE_AC_GLOBAL_DEBUG_H
+#define AGS_ENGINE_AC_GLOBAL_DEBUG_H
 
+//include <cstdio>
 #include "ags/shared/util/string.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/global_dialog.cpp b/engines/ags/engine/ac/global_dialog.cpp
index 0f63c7fef5..eb8c54ca01 100644
--- a/engines/ags/engine/ac/global_dialog.cpp
+++ b/engines/ags/engine/ac/global_dialog.cpp
@@ -23,9 +23,9 @@
 #include "ags/engine/ac/global_dialog.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/dialog.h"
-#include "ags/shared/ac/dialogtopic.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/dialog_topic.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/engine/debugging/debugger.h"
 #include "ags/shared/debugging/out.h"
@@ -47,7 +47,7 @@ void RunDialog(int tum) {
 			_GP(play).stop_dialog_at_end = DIALOG_NEWTOPIC + tum;
 		else
 			quitprintf("!RunDialog: two NewRoom/RunDialog/StopDialog requests within dialog; last was called in \"%s\", line %d",
-				_GP(last_in_dialog_request_script_pos).Section.GetCStr(), _GP(last_in_dialog_request_script_pos).Line);
+			           _GP(last_in_dialog_request_script_pos).Section.GetCStr(), _GP(last_in_dialog_request_script_pos).Line);
 		return;
 	}
 
diff --git a/engines/ags/engine/ac/global_dialog.h b/engines/ags/engine/ac/global_dialog.h
index 6100bd17f9..97eca20240 100644
--- a/engines/ags/engine/ac/global_dialog.h
+++ b/engines/ags/engine/ac/global_dialog.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBALDIALOG_H
-#define AGS_ENGINE_AC_GLOBALDIALOG_H
+#ifndef AGS_ENGINE_AC_GLOBAL_DIALOG_H
+#define AGS_ENGINE_AC_GLOBAL_DIALOG_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_display.cpp b/engines/ags/engine/ac/global_display.cpp
index 661a4310cf..27eadd397a 100644
--- a/engines/ags/engine/ac/global_display.cpp
+++ b/engines/ags/engine/ac/global_display.cpp
@@ -20,13 +20,15 @@
  *
  */
 
+//include <cstdio>
+//include <stdarg.h>
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/character.h"
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/game.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_display.h"
 #include "ags/engine/ac/global_screen.h"
@@ -34,11 +36,10 @@
 #include "ags/engine/ac/runtime_defines.h"
 #include "ags/engine/ac/speech.h"
 #include "ags/engine/ac/string.h"
-#include "ags/engine/ac/topbarsettings.h"
+#include "ags/engine/ac/top_bar_settings.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/engine/main/game_run.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
@@ -108,8 +109,8 @@ void DisplayMessageAtY(int msnum, int ypos) {
 	if (_G(display_message_aschar) > 0) {
 		_G(display_message_aschar) = 0;
 		quit("!DisplayMessage: data column specified a character for local\n"
-			"message; use the message editor to select the character for room\n"
-			"messages.\n");
+		     "message; use the message editor to select the character for room\n"
+		     "messages.\n");
 	}
 
 	int repeatloop = 1;
@@ -175,7 +176,7 @@ void DisplayAtY(int ypos, const char *texx) {
 		}
 
 		_display_at(-1, ypos, ui_view.GetWidth() / 2 + ui_view.GetWidth() / 4,
-			get_translation(texx), DISPLAYTEXT_MESSAGEBOX, 0, 0, 0, false);
+		            get_translation(texx), DISPLAYTEXT_MESSAGEBOX, 0, 0, 0, false);
 	}
 }
 
diff --git a/engines/ags/engine/ac/global_drawingsurface.cpp b/engines/ags/engine/ac/global_drawing_surface.cpp
similarity index 93%
rename from engines/ags/engine/ac/global_drawingsurface.cpp
rename to engines/ags/engine/ac/global_drawing_surface.cpp
index 418f09e422..043481ab3b 100644
--- a/engines/ags/engine/ac/global_drawingsurface.cpp
+++ b/engines/ags/engine/ac/global_drawing_surface.cpp
@@ -24,19 +24,18 @@
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/game.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
-#include "ags/engine/ac/global_drawingsurface.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
+#include "ags/engine/ac/global_drawing_surface.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/shared/font/fonts.h"
-#include "ags/shared/game/roomstruct.h"
-#include "ags/shared/gui/guidefines.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/game/room_struct.h"
+#include "ags/shared/gui/gui_defines.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/shared/gfx/gfx_def.h"
 #include "ags/engine/gfx/gfx_util.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
@@ -75,8 +74,8 @@ void RawRestoreScreenTinted(int red, int green, int blue, int opacity) {
 		return;
 	}
 	if ((red < 0) || (green < 0) || (blue < 0) ||
-		(red > 255) || (green > 255) || (blue > 255) ||
-		(opacity < 1) || (opacity > 100))
+	        (red > 255) || (green > 255) || (blue > 255) ||
+	        (opacity < 1) || (opacity > 100))
 		quit("!RawRestoreScreenTinted: invalid parameter. R,G,B must be 0-255, opacity 1-100");
 
 	debug_script_log("RawRestoreTinted RGB(%d,%d,%d) %d%%", red, green, blue, opacity);
@@ -89,7 +88,7 @@ void RawRestoreScreenTinted(int red, int green, int blue, int opacity) {
 
 void RawDrawFrameTransparent(int frame, int translev) {
 	if ((frame < 0) || ((size_t)frame >= _GP(thisroom).BgFrameCount) ||
-		(translev < 0) || (translev > 99))
+	        (translev < 0) || (translev > 99))
 		quit("!RawDrawFrameTransparent: invalid parameter (transparency must be 0-99, frame a valid BG frame)");
 
 	PBitmap bg = _GP(thisroom).BgFrames[frame].Graphic;
@@ -106,7 +105,7 @@ void RawDrawFrameTransparent(int frame, int translev) {
 	} else {
 		// Draw it transparently
 		GfxUtil::DrawSpriteWithTransparency(RAW_SURFACE(), bg.get(), 0, 0,
-			GfxDef::Trans100ToAlpha255(translev));
+		                                    GfxDef::Trans100ToAlpha255(translev));
 	}
 	invalidate_screen();
 	mark_current_background_dirty();
@@ -126,7 +125,7 @@ void RawSetColor(int clr) {
 }
 void RawSetColorRGB(int red, int grn, int blu) {
 	if ((red < 0) || (red > 255) || (grn < 0) || (grn > 255) ||
-		(blu < 0) || (blu > 255))
+	        (blu < 0) || (blu > 255))
 		quit("!RawSetColorRGB: colour values must be 0-255");
 
 	_GP(play).raw_color = makecol_depth(_GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth(), red, grn, blu);
@@ -157,13 +156,13 @@ void RawPrintMessageWrapped(int xx, int yy, int wid, int font, int msgm) {
 	// it's probably too late but check anyway
 	if (strlen(displbuf) > 2899)
 		quit("!RawPrintMessageWrapped: message too long");
-	if (break_up_text_into_lines(displbuf, _GP(fontLines), wid, font) == 0)
+	if (break_up_text_into_lines(displbuf, Lines, wid, font) == 0)
 		return;
 
 	RAW_START();
 	color_t text_color = _GP(play).raw_color;
-	for (size_t i = 0; i < _GP(fontLines).Count(); i++)
-		wouttext_outline(RAW_SURFACE(), xx, yy + linespacing * i, font, text_color, _GP(fontLines)[i]);
+	for (size_t i = 0; i < Lines.Count(); i++)
+		wouttext_outline(RAW_SURFACE(), xx, yy + linespacing * i, font, text_color, Lines[i]);
 	invalidate_screen();
 	mark_current_background_dirty();
 	RAW_END();
@@ -240,8 +239,8 @@ void RawDrawImageResized(int xx, int yy, int gotSlot, int width, int height) {
 	// resize the sprite to the requested size
 	Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, _GP(spriteset)[gotSlot]->GetColorDepth());
 	newPic->StretchBlt(_GP(spriteset)[gotSlot],
-		RectWH(0, 0, _GP(game).SpriteInfos[gotSlot].Width, _GP(game).SpriteInfos[gotSlot].Height),
-		RectWH(0, 0, width, height));
+	                   RectWH(0, 0, _GP(game).SpriteInfos[gotSlot].Width, _GP(game).SpriteInfos[gotSlot].Height),
+	                   RectWH(0, 0, width, height));
 
 	RAW_START();
 	if (newPic->GetColorDepth() != RAW_SURFACE()->GetColorDepth())
diff --git a/engines/ags/engine/ac/global_drawingsurface.h b/engines/ags/engine/ac/global_drawing_surface.h
similarity index 95%
rename from engines/ags/engine/ac/global_drawingsurface.h
rename to engines/ags/engine/ac/global_drawing_surface.h
index f6f8b81623..df0a9b3521 100644
--- a/engines/ags/engine/ac/global_drawingsurface.h
+++ b/engines/ags/engine/ac/global_drawing_surface.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBALDRAWINGSURFACE_H
-#define AGS_ENGINE_AC_GLOBALDRAWINGSURFACE_H
+#ifndef AGS_ENGINE_AC_GLOBAL_DRAWING_SURFACE_H
+#define AGS_ENGINE_AC_GLOBAL_DRAWING_SURFACE_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_dynamicsprite.cpp b/engines/ags/engine/ac/global_dynamic_sprite.cpp
similarity index 88%
rename from engines/ags/engine/ac/global_dynamicsprite.cpp
rename to engines/ags/engine/ac/global_dynamic_sprite.cpp
index e3800c48f5..3a9ce64ce3 100644
--- a/engines/ags/engine/ac/global_dynamicsprite.cpp
+++ b/engines/ags/engine/ac/global_dynamic_sprite.cpp
@@ -20,14 +20,13 @@
  *
  */
 
-#include "ags/engine/ac/global_dynamicsprite.h"
-#include "ags/shared/util/wgt2allg.h" // Allegro RGB, PALETTE
+#include "ags/engine/ac/global_dynamic_sprite.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/engine/ac/dynamicsprite.h"
+#include "ags/engine/ac/dynamic_sprite.h"
 #include "ags/engine/ac/path_helper.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/ac/runtime_defines.h" //MAX_PATH
-#include "ags/engine/gfx/graphicsdriver.h"
+#include "ags/engine/gfx/graphics_driver.h"
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/globals.h"
 
diff --git a/engines/ags/engine/ac/global_dynamicsprite.h b/engines/ags/engine/ac/global_dynamic_sprite.h
similarity index 92%
rename from engines/ags/engine/ac/global_dynamicsprite.h
rename to engines/ags/engine/ac/global_dynamic_sprite.h
index a294804917..f2ad016a33 100644
--- a/engines/ags/engine/ac/global_dynamicsprite.h
+++ b/engines/ags/engine/ac/global_dynamic_sprite.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBAL_DYNAMICSPRITE_H
-#define AGS_ENGINE_AC_GLOBAL_DYNAMICSPRITE_H
+#ifndef AGS_ENGINE_AC_GLOBALDYNAMICSPRITE_H
+#define AGS_ENGINE_AC_GLOBALDYNAMICSPRITE_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_file.cpp b/engines/ags/engine/ac/global_file.cpp
index ed05d06175..b18627ce03 100644
--- a/engines/ags/engine/ac/global_file.cpp
+++ b/engines/ags/engine/ac/global_file.cpp
@@ -28,7 +28,6 @@
 #include "ags/engine/ac/string.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/shared/util/directory.h"
-#include "ags/shared/util/filestream.h"
 #include "ags/shared/util/path.h"
 #include "ags/shared/util/stream.h"
 
@@ -59,7 +58,7 @@ int32_t FindFreeFileSlot() {
 	}
 
 	if (useindx >= num_open_script_files &&
-		num_open_script_files >= MAX_OPEN_SCRIPT_FILES) {
+	        num_open_script_files >= MAX_OPEN_SCRIPT_FILES) {
 		quit("!FileOpen: tried to open more than 10 files simultaneously - close some first");
 		return -1;
 	}
@@ -81,9 +80,8 @@ int32_t FileOpen(const char *fnmm, Shared::FileOpenMode open_mode, Shared::FileW
 	}
 
 	Stream *s = File::OpenFile(rp.FullPath, open_mode, work_mode);
-	if (!s && !rp.AltPath.IsEmpty() && rp.AltPath.Compare(rp.FullPath) != 0) {
+	if (!s && !rp.AltPath.IsEmpty() && rp.AltPath.Compare(rp.FullPath) != 0)
 		s = File::OpenFile(rp.AltPath, open_mode, work_mode);
-	}
 
 	valid_handles[useindx].stream = s;
 	if (valid_handles[useindx].stream == nullptr)
diff --git a/engines/ags/engine/ac/global_file.h b/engines/ags/engine/ac/global_file.h
index 1392c5859b..ace904dbdc 100644
--- a/engines/ags/engine/ac/global_file.h
+++ b/engines/ags/engine/ac/global_file.h
@@ -20,12 +20,13 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBAL_FILE_H
-#define AGS_ENGINE_AC_GLOBAL_FILE_H
+#ifndef AGS_ENGINE_AC_GLOBALFILE_H
+#define AGS_ENGINE_AC_GLOBALFILE_H
 
 #include "ags/shared/util/file.h"
 
 namespace AGS3 {
+
 namespace AGS {
 namespace Shared {
 class Stream;
diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 44c22dba85..72155c8166 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -20,63 +20,64 @@
  *
  */
 
+#include "ags/lib/std/math.h"
 #include "ags/shared/core/platform.h"
-#include "ags/shared/ac/audiocliptype.h"
-#include "ags/shared/util/path.h"
+#include "ags/shared/ac/audio_clip_type.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/shared/ac/common.h"
 #include "ags/shared/ac/view.h"
 #include "ags/engine/ac/character.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/engine/ac/dynamicsprite.h"
+#include "ags/engine/ac/dynamic_sprite.h"
 #include "ags/engine/ac/event.h"
 #include "ags/engine/ac/game.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_gui.h"
 #include "ags/engine/ac/global_hotspot.h"
-#include "ags/engine/ac/global_inventoryitem.h"
+#include "ags/engine/ac/global_inventory_item.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/gui.h"
 #include "ags/engine/ac/hotspot.h"
-#include "ags/engine/ac/keycode.h"
+#include "ags/shared/ac/keycode.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/ac/object.h"
 #include "ags/engine/ac/path_helper.h"
 #include "ags/engine/ac/sys_events.h"
 #include "ags/engine/ac/room.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/ac/system.h"
 #include "ags/engine/debugging/debugger.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/engine/gui/guidialog.h"
+#include "ags/engine/gui/gui_dialog.h"
 #include "ags/engine/main/engine.h"
-#include "ags/engine/main/game_start.h"
 #include "ags/engine/main/game_run.h"
 #include "ags/engine/main/graphics_mode.h"
+#include "ags/engine/main/game_start.h"
 #include "ags/engine/script/script.h"
 #include "ags/engine/script/script_runtime.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/shared/gfx/bitmap.h"
-#include "ags/engine/gfx/graphicsdriver.h"
-#include "ags/shared/core/assetmanager.h"
+#include "ags/engine/gfx/graphics_driver.h"
+#include "ags/shared/core/asset_manager.h"
 #include "ags/engine/main/config.h"
 #include "ags/engine/main/game_file.h"
+#include "ags/shared/util/path.h"
 #include "ags/shared/util/string_utils.h"
 #include "ags/engine/media/audio/audio_system.h"
+#include "ags/engine/platform/base/sys_main.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
-#define ALLEGRO_KEYBOARD_HANDLER
-
 void GiveScore(int amnt) {
-	_G(guis_need_update) = 1;
+	GUI::MarkSpecialLabelsForUpdate(kLabelMacro_AllScore);
 	_GP(play).score += amnt;
 
 	if ((amnt > 0) && (_GP(play).score_sound >= 0))
@@ -109,19 +110,7 @@ void RestoreGameSlot(int slnum) {
 void DeleteSaveSlot(int slnum) {
 	String nametouse;
 	nametouse = get_save_game_path(slnum);
-	Shared::File::DeleteFile(nametouse);
-	// The code below renames the highest save game to fill in the gap
-	// This does not work (because the system rename() function does not
-	// handle our "/saves/" prefix). We could remove it here and use
-	// g_system->getSavefileManager()->renameSavefile. But it might
-	// actually be better to not fill the gap. The original AGS engine
-	// sorts savegame by date, but as we don't have access to the date,
-	// we save them by slot. So moving the highest slot to the gap may
-	// not be a good idea. An alternative would be to shift by one all
-	// the savegames after the removed one.
-	// One aspect to keep in mind is that MAXSAVEGAMES is 50, but we
-	// allow slot up to 099. So we have some margin.
-#ifndef AGS_PLATFORM_SCUMMVM
+	::remove(nametouse);
 	if ((slnum >= 1) && (slnum <= MAXSAVEGAMES)) {
 		String thisname;
 		for (int i = MAXSAVEGAMES; i > slnum; i--) {
@@ -134,7 +123,6 @@ void DeleteSaveSlot(int slnum) {
 		}
 
 	}
-#endif
 }
 
 void PauseGame() {
@@ -153,15 +141,19 @@ int IsGamePaused() {
 	return 0;
 }
 
+bool GetSaveSlotDescription(int slnum, String &description) {
+	if (read_savedgame_description(get_save_game_path(slnum), description))
+		return true;
+	description.Format("INVALID SLOT %d", slnum);
+	return false;
+}
+
 int GetSaveSlotDescription(int slnum, char *desbuf) {
 	VALIDATE_STRING(desbuf);
 	String description;
-	if (read_savedgame_description(get_save_game_path(slnum), description)) {
-		strcpy(desbuf, description);
-		return 1;
-	}
-	sprintf(desbuf, "INVALID SLOT %d", slnum);
-	return 0;
+	bool res = GetSaveSlotDescription(slnum, description);
+	snprintf(desbuf, MAX_MAXSTRLEN, "%s", description.GetCStr());
+	return res ? 1 : 0;
 }
 
 int LoadSaveSlotScreenshot(int slnum, int width, int height) {
@@ -180,8 +172,8 @@ int LoadSaveSlotScreenshot(int slnum, int width, int height) {
 	// resize the sprite to the requested size
 	Bitmap *newPic = BitmapHelper::CreateBitmap(width, height, _GP(spriteset)[gotSlot]->GetColorDepth());
 	newPic->StretchBlt(_GP(spriteset)[gotSlot],
-		RectWH(0, 0, _GP(game).SpriteInfos[gotSlot].Width, _GP(game).SpriteInfos[gotSlot].Height),
-		RectWH(0, 0, width, height));
+	                   RectWH(0, 0, _GP(game).SpriteInfos[gotSlot].Width, _GP(game).SpriteInfos[gotSlot].Height),
+	                   RectWH(0, 0, width, height));
 
 	update_polled_stuff_if_runtime();
 
@@ -192,6 +184,31 @@ int LoadSaveSlotScreenshot(int slnum, int width, int height) {
 	return gotSlot;
 }
 
+void FillSaveList(std::vector<SaveListItem> &saves, size_t max_count) {
+	if (max_count == 0)
+		return; // duh
+
+	String svg_dir = get_save_game_directory();
+	String svg_suff = get_save_game_suffix();
+	String searchPath = Path::ConcatPaths(svg_dir, String::FromFormat("agssave.???%s", svg_suff.GetCStr()));
+	time_t time = 0;
+
+	SaveStateList saveList = ::AGS::g_vm->listSaves();
+	for (uint idx = 0; idx < saveList.size(); ++idx) {
+		int saveGameSlot = saveList[idx].getSaveSlot();
+
+		// only list games .000 to .099 (to allow higher slots for other perposes)
+		if (saveGameSlot > 99)
+			continue;
+
+		String description;
+		GetSaveSlotDescription(saveGameSlot, description);
+		saves.push_back(SaveListItem(saveGameSlot, description, time));
+		if (saves.size() >= max_count)
+			break;
+	}
+}
+
 void SetGlobalInt(int index, int valu) {
 	if ((index < 0) | (index >= MAXGSVALUES))
 		quit("!SetGlobalInt: invalid index");
@@ -240,10 +257,8 @@ int RunAGSGame(const char *newgame, unsigned int mode, int data) {
 	}
 
 	if ((mode & RAGMODE_LOADNOW) == 0) {
-		// need to copy, since the script gets destroyed
-		get_install_dir_path(_G(gamefilenamebuf), newgame);
-		_GP(ResPaths).GamePak.Path = _G(gamefilenamebuf);
-		_GP(ResPaths).GamePak.Name = Shared::Path::get_filename(_G(gamefilenamebuf));
+		_GP(ResPaths).GamePak.Path = PathFromInstallDir(newgame);
+		_GP(ResPaths).GamePak.Name = newgame;
 		_GP(play).takeover_data = data;
 		_G(load_new_game_restore) = -1;
 
@@ -261,14 +276,20 @@ int RunAGSGame(const char *newgame, unsigned int mode, int data) {
 	unload_old_room();
 	_G(displayed_room) = -10;
 
+#if defined (AGS_AUTO_WRITE_USER_CONFIG)
 	save_config_file(); // save current user config in case engine fails to run new game
+#endif // AGS_AUTO_WRITE_USER_CONFIG
 	unload_game_file();
 
 	// Adjust config (NOTE: normally, RunAGSGame would need a redesign to allow separate config etc per each game)
 	_GP(usetup).translation = ""; // reset to default, prevent from trying translation file of game A in game B
 
-	if (Shared::AssetManager::SetDataFile(_GP(ResPaths).GamePak.Path) != Shared::kAssetNoError)
+	_GP(AssetMgr)->RemoveAllLibraries();
+
+	// TODO: refactor and share same code with the startup!
+	if (_GP(AssetMgr)->AddLibrary(_GP(ResPaths).GamePak.Path) != Shared::kAssetNoError)
 		quitprintf("!RunAGSGame: unable to load new game file '%s'", _GP(ResPaths).GamePak.Path.GetCStr());
+	engine_assign_assetpaths();
 
 	show_preload();
 
@@ -312,8 +333,7 @@ int GetGameParameter(int parm, int data1, int data2, int data3) {
 	case GP_FRAMESPEED:
 	case GP_FRAMEIMAGE:
 	case GP_FRAMESOUND:
-	case GP_ISFRAMEFLIPPED:
-	{
+	case GP_ISFRAMEFLIPPED: {
 		if ((data1 < 1) || (data1 > _GP(game).numviews)) {
 			quitprintf("!GetGameParameter: invalid view specified (v: %d, l: %d, f: %d)", data1, data2, data3);
 		}
@@ -336,7 +356,6 @@ int GetGameParameter(int parm, int data1, int data2, int data3) {
 			return (pvf->flags & VFLG_FLIPSPRITE) ? 1 : 0;
 		else
 			quit("GetGameParameter internal error");
-		return 0;
 	}
 	case GP_ISRUNNEXTLOOP:
 		return Game_GetRunNextSettingForLoop(data1, data2);
@@ -410,9 +429,13 @@ int SetGameOption(int opt, int setting) {
 
 	if (opt == OPT_DUPLICATEINV)
 		update_invorder();
-	else if (opt == OPT_DISABLEOFF)
+	else if (opt == OPT_DISABLEOFF) {
 		_G(gui_disabled_style) = convert_gui_disabled_style(_GP(game).options[OPT_DISABLEOFF]);
-	else if (opt == OPT_PORTRAITSIDE) {
+		// If GUI was disabled at this time then also update it, as visual style could've changed
+		if (_GP(play).disabled_user_interface > 0) {
+			GUI::MarkAllGUIForUpdate();
+		}
+	} else if (opt == OPT_PORTRAITSIDE) {
 		if (setting == 0)  // set back to Left
 			_GP(play).swap_portrait_side = 0;
 	}
@@ -459,7 +482,7 @@ void StartCutscene(int skipwith) {
 
 	if (is_in_cutscene()) {
 		quitprintf("!StartCutscene: already in a cutscene; previous started in \"%s\", line %d",
-			last_cutscene_script_pos.Section.GetCStr(), last_cutscene_script_pos.Line);
+		           last_cutscene_script_pos.Section.GetCStr(), last_cutscene_script_pos.Line);
 	}
 
 	if ((skipwith < 1) || (skipwith > 6))
@@ -533,12 +556,12 @@ void GetLocationName(int xxx, int yyy, char *tempo) {
 		int mover = GetInvAt(xxx, yyy);
 		if (mover > 0) {
 			if (_GP(play).get_loc_name_last_time != 1000 + mover)
-				_G(guis_need_update) = 1;
+				GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 			_GP(play).get_loc_name_last_time = 1000 + mover;
 			strcpy(tempo, get_translation(_GP(game).invinfo[mover].name));
 		} else if ((_GP(play).get_loc_name_last_time > 1000) && (_GP(play).get_loc_name_last_time < 1000 + MAX_INV)) {
 			// no longer selecting an item
-			_G(guis_need_update) = 1;
+			GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 			_GP(play).get_loc_name_last_time = -1;
 		}
 		return;
@@ -557,7 +580,7 @@ void GetLocationName(int xxx, int yyy, char *tempo) {
 	if (loctype == 0) {
 		if (_GP(play).get_loc_name_last_time != 0) {
 			_GP(play).get_loc_name_last_time = 0;
-			_G(guis_need_update) = 1;
+			GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 		}
 		return;
 	}
@@ -567,7 +590,7 @@ void GetLocationName(int xxx, int yyy, char *tempo) {
 		onhs = _G(getloctype_index);
 		strcpy(tempo, get_translation(_GP(game).chars[onhs].name));
 		if (_GP(play).get_loc_name_last_time != 2000 + onhs)
-			_G(guis_need_update) = 1;
+			GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 		_GP(play).get_loc_name_last_time = 2000 + onhs;
 		return;
 	}
@@ -582,253 +605,24 @@ void GetLocationName(int xxx, int yyy, char *tempo) {
 			tempo[1] = 0;
 		}
 		if (_GP(play).get_loc_name_last_time != 3000 + aa)
-			_G(guis_need_update) = 1;
+			GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 		_GP(play).get_loc_name_last_time = 3000 + aa;
 		return;
 	}
 	onhs = _G(getloctype_index);
-	if (onhs > 0)
-		strcpy(tempo, get_translation(_GP(thisroom).Hotspots[onhs].Name));
+	if (onhs > 0) strcpy(tempo, get_translation(_GP(thisroom).Hotspots[onhs].Name));
 	if (_GP(play).get_loc_name_last_time != onhs)
-		_G(guis_need_update) = 1;
+		GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 	_GP(play).get_loc_name_last_time = onhs;
 }
 
 int IsKeyPressed(int keycode) {
-	if (keyboard_needs_poll())
-		poll_keyboard();
-
-	switch (keycode) {
-	case eAGSKeyCodeBackspace:
-		return ags_iskeypressed(__allegro_KEY_BACKSPACE);
-	case eAGSKeyCodeTab:
-		return ags_iskeypressed(__allegro_KEY_TAB);
-	case eAGSKeyCodeReturn:
-		return ags_iskeypressed(__allegro_KEY_ENTER) || ags_iskeypressed(__allegro_KEY_ENTER_PAD);
-	case eAGSKeyCodeEscape:
-		return ags_iskeypressed(__allegro_KEY_ESC);
-	case eAGSKeyCodeSpace:
-		return ags_iskeypressed(__allegro_KEY_SPACE);
-	case eAGSKeyCodeSingleQuote:
-		return ags_iskeypressed(__allegro_KEY_QUOTE);
-	case eAGSKeyCodeComma:
-		return ags_iskeypressed(__allegro_KEY_COMMA);
-	case eAGSKeyCodePeriod:
-		return ags_iskeypressed(__allegro_KEY_STOP);
-	case eAGSKeyCodeForwardSlash:
-		return ags_iskeypressed(__allegro_KEY_SLASH) || ags_iskeypressed(__allegro_KEY_SLASH_PAD);
-	case eAGSKeyCodeBackSlash:
-		return ags_iskeypressed(__allegro_KEY_BACKSLASH) || ags_iskeypressed(__allegro_KEY_BACKSLASH2);
-	case eAGSKeyCodeSemiColon:
-		return ags_iskeypressed(__allegro_KEY_SEMICOLON);
-	case eAGSKeyCodeEquals:
-		return ags_iskeypressed(__allegro_KEY_EQUALS) || ags_iskeypressed(__allegro_KEY_EQUALS_PAD);
-	case eAGSKeyCodeOpenBracket:
-		return ags_iskeypressed(__allegro_KEY_OPENBRACE);
-	case eAGSKeyCodeCloseBracket:
-		return ags_iskeypressed(__allegro_KEY_CLOSEBRACE);
-	// NOTE: we're treating EQUALS like PLUS, even though it is only available shifted.
-	case eAGSKeyCodePlus:
-		return ags_iskeypressed(__allegro_KEY_EQUALS) || ags_iskeypressed(__allegro_KEY_PLUS_PAD);
-	case eAGSKeyCodeHyphen:
-		return ags_iskeypressed(__allegro_KEY_MINUS) || ags_iskeypressed(__allegro_KEY_MINUS_PAD);
-
-	// non-shifted versions of keys
-	case eAGSKeyCodeColon:
-		return ags_iskeypressed(__allegro_KEY_COLON) || ags_iskeypressed(__allegro_KEY_COLON2);
-	case eAGSKeyCodeAsterisk:
-		return ags_iskeypressed(__allegro_KEY_ASTERISK);
-	case eAGSKeyCodeAt:
-		return ags_iskeypressed(__allegro_KEY_AT);
-
-	case eAGSKeyCode0:
-		return ags_iskeypressed(__allegro_KEY_0);
-	case eAGSKeyCode1:
-		return ags_iskeypressed(__allegro_KEY_1);
-	case eAGSKeyCode2:
-		return ags_iskeypressed(__allegro_KEY_2);
-	case eAGSKeyCode3:
-		return ags_iskeypressed(__allegro_KEY_3);
-	case eAGSKeyCode4:
-		return ags_iskeypressed(__allegro_KEY_4);
-	case eAGSKeyCode5:
-		return ags_iskeypressed(__allegro_KEY_5);
-	case eAGSKeyCode6:
-		return ags_iskeypressed(__allegro_KEY_6);
-	case eAGSKeyCode7:
-		return ags_iskeypressed(__allegro_KEY_7);
-	case eAGSKeyCode8:
-		return ags_iskeypressed(__allegro_KEY_8);
-	case eAGSKeyCode9:
-		return ags_iskeypressed(__allegro_KEY_9);
-
-	case eAGSKeyCodeA:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('A'));
-	case eAGSKeyCodeB:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('B'));
-	case eAGSKeyCodeC:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('C'));
-	case eAGSKeyCodeD:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('D'));
-	case eAGSKeyCodeE:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('E'));
-	case eAGSKeyCodeF:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('F'));
-	case eAGSKeyCodeG:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('G'));
-	case eAGSKeyCodeH:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('H'));
-	case eAGSKeyCodeI:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('I'));
-	case eAGSKeyCodeJ:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('J'));
-	case eAGSKeyCodeK:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('K'));
-	case eAGSKeyCodeL:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('L'));
-	case eAGSKeyCodeM:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('M'));
-	case eAGSKeyCodeN:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('N'));
-	case eAGSKeyCodeO:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('O'));
-	case eAGSKeyCodeP:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('P'));
-	case eAGSKeyCodeQ:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('Q'));
-	case eAGSKeyCodeR:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('R'));
-	case eAGSKeyCodeS:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('S'));
-	case eAGSKeyCodeT:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('T'));
-	case eAGSKeyCodeU:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('U'));
-	case eAGSKeyCodeV:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('V'));
-	case eAGSKeyCodeW:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('W'));
-	case eAGSKeyCodeX:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('X'));
-	case eAGSKeyCodeY:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('Y'));
-	case eAGSKeyCodeZ:
-		return ags_iskeypressed(_G(platform)->ConvertKeycodeToScanCode('Z'));
-
-	case eAGSKeyCodeF1:
-		return ags_iskeypressed(__allegro_KEY_F1);
-	case eAGSKeyCodeF2:
-		return ags_iskeypressed(__allegro_KEY_F2);
-	case eAGSKeyCodeF3:
-		return ags_iskeypressed(__allegro_KEY_F3);
-	case eAGSKeyCodeF4:
-		return ags_iskeypressed(__allegro_KEY_F4);
-	case eAGSKeyCodeF5:
-		return ags_iskeypressed(__allegro_KEY_F5);
-	case eAGSKeyCodeF6:
-		return ags_iskeypressed(__allegro_KEY_F6);
-	case eAGSKeyCodeF7:
-		return ags_iskeypressed(__allegro_KEY_F7);
-	case eAGSKeyCodeF8:
-		return ags_iskeypressed(__allegro_KEY_F8);
-	case eAGSKeyCodeF9:
-		return ags_iskeypressed(__allegro_KEY_F9);
-	case eAGSKeyCodeF10:
-		return ags_iskeypressed(__allegro_KEY_F10);
-	case eAGSKeyCodeF11:
-		return ags_iskeypressed(__allegro_KEY_F11);
-	case eAGSKeyCodeF12:
-		return ags_iskeypressed(__allegro_KEY_F12);
-
-	case eAGSKeyCodeHome:
-		return ags_iskeypressed(__allegro_KEY_HOME) || ags_iskeypressed(__allegro_KEY_7_PAD);
-	case eAGSKeyCodeUpArrow:
-		return ags_iskeypressed(__allegro_KEY_UP) || ags_iskeypressed(__allegro_KEY_8_PAD);
-	case eAGSKeyCodePageUp:
-		return ags_iskeypressed(__allegro_KEY_PGUP) || ags_iskeypressed(__allegro_KEY_9_PAD);
-	case eAGSKeyCodeLeftArrow:
-		return ags_iskeypressed(__allegro_KEY_LEFT) || ags_iskeypressed(__allegro_KEY_4_PAD);
-	case eAGSKeyCodeNumPad5:
-		return ags_iskeypressed(__allegro_KEY_5_PAD);
-	case eAGSKeyCodeRightArrow:
-		return ags_iskeypressed(__allegro_KEY_RIGHT) || ags_iskeypressed(__allegro_KEY_6_PAD);
-	case eAGSKeyCodeEnd:
-		return ags_iskeypressed(__allegro_KEY_END) || ags_iskeypressed(__allegro_KEY_1_PAD);
-	case eAGSKeyCodeDownArrow:
-		return ags_iskeypressed(__allegro_KEY_DOWN) || ags_iskeypressed(__allegro_KEY_2_PAD);
-	case eAGSKeyCodePageDown:
-		return ags_iskeypressed(__allegro_KEY_PGDN) || ags_iskeypressed(__allegro_KEY_3_PAD);
-	case eAGSKeyCodeInsert:
-		return ags_iskeypressed(__allegro_KEY_INSERT) || ags_iskeypressed(__allegro_KEY_0_PAD);
-	case eAGSKeyCodeDelete:
-		return ags_iskeypressed(__allegro_KEY_DEL) || ags_iskeypressed(__allegro_KEY_DEL_PAD);
-
-	// These keys are not defined in the eAGSKey enum but are in the manual
-	// https://adventuregamestudio.github.io/ags-manual/ASCIIcodes.html
-
-	case 403:
-		return ags_iskeypressed(__allegro_KEY_LSHIFT);
-	case 404:
-		return ags_iskeypressed(__allegro_KEY_RSHIFT);
-	case 405:
-		return ags_iskeypressed(__allegro_KEY_LCONTROL);
-	case 406:
-		return ags_iskeypressed(__allegro_KEY_RCONTROL);
-	case 407:
-		return ags_iskeypressed(__allegro_KEY_ALT);
-
-	// (noted here for interest)
-	// The following are the AGS_EXT_KEY_SHIFT, derived from applying arithmetic to the original keycodes.
-	// These do not have a corresponding ags key enum, do not appear in the manual and may not be accessible because of OS contraints.
-
-	case 392:
-		return ags_iskeypressed(__allegro_KEY_PRTSCR);
-	case 393:
-		return ags_iskeypressed(__allegro_KEY_PAUSE);
-	case 394:
-		return ags_iskeypressed(__allegro_KEY_ABNT_C1);
-	case 395:
-		return ags_iskeypressed(__allegro_KEY_YEN);
-	case 396:
-		return ags_iskeypressed(__allegro_KEY_KANA);
-	case 397:
-		return ags_iskeypressed(__allegro_KEY_CONVERT);
-	case 398:
-		return ags_iskeypressed(__allegro_KEY_NOCONVERT);
-	case 400:
-		return ags_iskeypressed(__allegro_KEY_CIRCUMFLEX);
-	case 402:
-		return ags_iskeypressed(__allegro_KEY_KANJI);
-	case 420:
-		return ags_iskeypressed(__allegro_KEY_ALTGR);
-	case 421:
-		return ags_iskeypressed(__allegro_KEY_LWIN);
-	case 422:
-		return ags_iskeypressed(__allegro_KEY_RWIN);
-	case 423:
-		return ags_iskeypressed(__allegro_KEY_MENU);
-	case 424:
-		return ags_iskeypressed(__allegro_KEY_SCRLOCK);
-	case 425:
-		return ags_iskeypressed(__allegro_KEY_NUMLOCK);
-	case 426:
-		return ags_iskeypressed(__allegro_KEY_CAPSLOCK);
-
-	// Allegro4 keys that were never supported:
-	// __allegro_KEY_COMMAND
-	// __allegro_KEY_TILDE
-	// __allegro_KEY_BACKQUOTE
-
-	default:
-		// Remaining Allegro4 keycodes are offset by AGS_EXT_KEY_SHIFT
-		if (keycode >= AGS_EXT_KEY_SHIFT) {
-			if (ags_iskeypressed(keycode - AGS_EXT_KEY_SHIFT)) {
-				return 1;
-			}
-		}
+	auto status = ags_iskeydown(static_cast<eAGSKeyCode>(keycode));
+	if (status < 0) {
 		debug_script_log("IsKeyPressed: unsupported keycode %d", keycode);
 		return 0;
 	}
+	return status;
 }
 
 int SaveScreenShot(const char *namm) {
@@ -836,12 +630,12 @@ int SaveScreenShot(const char *namm) {
 	String svg_dir = get_save_game_directory();
 
 	if (strchr(namm, '.') == nullptr)
-		fileName.Format("%s%s.bmp", svg_dir.GetCStr(), namm);
+		fileName = Path::MakePath(svg_dir, namm, "bmp");
 	else
-		fileName.Format("%s%s", svg_dir.GetCStr(), namm);
+		fileName = Path::ConcatPaths(svg_dir, namm);
 
 	Bitmap *buffer = CopyScreenIntoBitmap(_GP(play).GetMainViewport().GetWidth(), _GP(play).GetMainViewport().GetHeight());
-	if (!buffer->SaveToFile(fileName, _G(palette))) {
+	if (!buffer->SaveToFile(fileName, _G(palette)) != 0) {
 		delete buffer;
 		return 0;
 	}
@@ -861,17 +655,13 @@ void SetMultitasking(int mode) {
 	if ((mode == 1) && (!_GP(scsystem).windowed))
 		mode = 0;
 
+	// Install engine callbacks for switching in and out the window
 	if (mode == 0) {
-		if (set_display_switch_mode(SWITCH_PAUSE) == -1)
-			set_display_switch_mode(SWITCH_AMNESIA);
-		// install callbacks to stop the sound when switching away
-		set_display_switch_callback(SWITCH_IN, display_switch_in_resume);
-		set_display_switch_callback(SWITCH_OUT, display_switch_out_suspend);
+		sys_set_background_mode(false);
+		sys_evt_set_focus_callbacks(display_switch_in_resume, display_switch_out_suspend);
 	} else {
-		if (set_display_switch_mode(SWITCH_BACKGROUND) == -1)
-			set_display_switch_mode(SWITCH_BACKAMNESIA);
-		set_display_switch_callback(SWITCH_IN, display_switch_in);
-		set_display_switch_callback(SWITCH_OUT, display_switch_out);
+		sys_set_background_mode(true);
+		sys_evt_set_focus_callbacks(display_switch_in, display_switch_out);
 	}
 }
 
@@ -991,26 +781,17 @@ void SetGraphicalVariable(const char *varName, int p_value) {
 }
 
 int WaitImpl(int skip_type, int nloops) {
+	if ((nloops < 1) && (_G(loaded_game_file_version) >= kGameVersion_262)) // 2.62+
+		quit("!Wait: must wait at least 1 loop");
+
 	_GP(play).wait_counter = nloops;
-	_GP(play).wait_skipped_by = SKIP_AUTOTIMER; // we set timer flag by default to simplify that case
-	_GP(play).wait_skipped_by_data = 0;
 	_GP(play).key_skip_wait = skip_type;
 
-	GameLoopUntilValueIsZero(&_GP(play).wait_counter);
+	GameLoopUntilValueIsZeroOrLess(&_GP(play).wait_counter);
 
-	if (_GP(game).options[OPT_BASESCRIPTAPI] < kScriptAPI_v351) {
-		// < 3.5.1 return 1 is skipped by user input, otherwise 0
-		return (_GP(play).wait_skipped_by & (SKIP_KEYPRESS | SKIP_MOUSECLICK)) != 0 ? 1 : 0;
-	}
-	// >= 3.5.1 return positive keycode, negative mouse button code, or 0 as time-out
-	switch (_GP(play).wait_skipped_by) {
-	case SKIP_KEYPRESS:
-		return _GP(play).wait_skipped_by_data;
-	case SKIP_MOUSECLICK:
-		return -(_GP(play).wait_skipped_by_data + 1); // convert to 1-based code and negate
-	default:
-		return 0;
-	}
+	if (_GP(play).wait_counter < 0)
+		return 1;
+	return 0;
 }
 
 void scrWait(int nloops) {
@@ -1021,16 +802,8 @@ int WaitKey(int nloops) {
 	return WaitImpl(SKIP_KEYPRESS | SKIP_AUTOTIMER, nloops);
 }
 
-int WaitMouse(int nloops) {
-	return WaitImpl(SKIP_MOUSECLICK | SKIP_AUTOTIMER, nloops);
-}
-
 int WaitMouseKey(int nloops) {
 	return WaitImpl(SKIP_KEYPRESS | SKIP_MOUSECLICK | SKIP_AUTOTIMER, nloops);
 }
 
-void SkipWait() {
-	_GP(play).wait_counter = 0;
-}
-
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/global_game.h b/engines/ags/engine/ac/global_game.h
index 8280887aa5..1add95664a 100644
--- a/engines/ags/engine/ac/global_game.h
+++ b/engines/ags/engine/ac/global_game.h
@@ -29,12 +29,28 @@ namespace AGS3 {
 
 using namespace AGS; // FIXME later
 
+struct SaveListItem {
+	int    Slot;
+	Shared::String Description;
+	time_t FileTime = 0;
+
+	SaveListItem(int slot, const Shared::String &desc, time_t ft)
+		: Slot(slot), Description(desc), FileTime(ft) {
+	}
+
+	inline bool operator < (const SaveListItem &other) const {
+		return FileTime < other.FileTime;
+	}
+};
+
+
 void GiveScore(int amnt);
 void restart_game();
 void RestoreGameSlot(int slnum);
 void DeleteSaveSlot(int slnum);
 int  GetSaveSlotDescription(int slnum, char *desbuf);
 int  LoadSaveSlotScreenshot(int slnum, int width, int height);
+void FillSaveList(std::vector<SaveListItem> &saves, size_t max_count = -1);
 void PauseGame();
 void UnPauseGame();
 int  IsGamePaused();
@@ -89,9 +105,7 @@ int GetGraphicalVariable(const char *varName);
 void SetGraphicalVariable(const char *varName, int p_value);
 void scrWait(int nloops);
 int WaitKey(int nloops);
-int WaitMouse(int nloops);
 int WaitMouseKey(int nloops);
-void SkipWait();
 
 } // namespace AGS3
 
diff --git a/engines/ags/engine/ac/global_gui.cpp b/engines/ags/engine/ac/global_gui.cpp
index ed2dd211ab..8f1f32e850 100644
--- a/engines/ags/engine/ac/global_gui.cpp
+++ b/engines/ags/engine/ac/global_gui.cpp
@@ -23,19 +23,19 @@
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/global_gui.h"
 #include "ags/engine/ac/gui.h"
-#include "ags/engine/ac/guicontrol.h"
+#include "ags/engine/ac/gui_control.h"
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/shared/font/fonts.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/engine/script/runtimescriptvalue.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/engine/script/runtime_script_value.h"
 #include "ags/shared/util/string_compat.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
@@ -75,7 +75,6 @@ void InterfaceOn(int ifn) {
 		debug_script_log("GUIOn(%d) ignored (already on)", ifn);
 		return;
 	}
-	_G(guis_need_update) = 1;
 	_GP(guis)[ifn].SetVisible(true);
 	debug_script_log("GUI %d turned on", ifn);
 	// modal interface
@@ -99,7 +98,6 @@ void InterfaceOff(int ifn) {
 		_GP(guis)[ifn].MouseOverCtrl = -1;
 	}
 	_GP(guis)[ifn].OnControlPositionChanged();
-	_G(guis_need_update) = 1;
 	// modal interface
 	if (_GP(guis)[ifn].PopupStyle == kGUIPopupModal) UnPauseGame();
 }
@@ -188,9 +186,9 @@ int GetTextHeight(const char *text, int fontnum, int width) {
 	if ((fontnum < 0) || (fontnum >= _GP(game).numfonts))
 		quit("!GetTextHeight: invalid font number.");
 
-	if (break_up_text_into_lines(text, _GP(fontLines), data_to_game_coord(width), fontnum) == 0)
+	if (break_up_text_into_lines(text, Lines, data_to_game_coord(width), fontnum) == 0)
 		return 0;
-	return game_to_data_coord(getheightoflines(fontnum, _GP(fontLines).Count()));
+	return game_to_data_coord(getheightoflines(fontnum, Lines.Count()));
 }
 
 int GetFontHeight(int fontnum) {
@@ -213,17 +211,22 @@ void SetGUIBackgroundPic(int guin, int slotn) {
 }
 
 void DisableInterface() {
+	if (_GP(play).disabled_user_interface == 0 && // only if was enabled before
+	        _G(gui_disabled_style) != GUIDIS_UNCHANGED) { // If GUI looks change when disabled, then update them all
+		GUI::MarkAllGUIForUpdate();
+	}
 	_GP(play).disabled_user_interface++;
-	_G(guis_need_update) = 1;
 	set_mouse_cursor(CURS_WAIT);
 }
 
 void EnableInterface() {
-	_G(guis_need_update) = 1;
 	_GP(play).disabled_user_interface--;
 	if (_GP(play).disabled_user_interface < 1) {
 		_GP(play).disabled_user_interface = 0;
 		set_default_cursor();
+		if (_G(gui_disabled_style) != GUIDIS_UNCHANGED) { // If GUI looks change when disabled, then update them all
+			GUI::MarkAllGUIForUpdate();
+		}
 	}
 }
 // Returns 1 if user interface is enabled, 0 if disabled
diff --git a/engines/ags/engine/ac/global_hotspot.cpp b/engines/ags/engine/ac/global_hotspot.cpp
index 75bc18bb05..3f88270938 100644
--- a/engines/ags/engine/ac/global_hotspot.cpp
+++ b/engines/ags/engine/ac/global_hotspot.cpp
@@ -23,25 +23,31 @@
 #include "ags/engine/ac/global_hotspot.h"
 #include "ags/shared/ac/common.h"
 #include "ags/shared/ac/common_defines.h"
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/event.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/hotspot.h"
 #include "ags/engine/ac/properties.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/engine/script/script.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
+
+
+
+
+
+
 void DisableHotspot(int hsnum) {
 	if ((hsnum < 1) | (hsnum >= MAX_ROOM_HOTSPOTS))
 		quit("!DisableHotspot: invalid hotspot specified");
@@ -78,8 +84,12 @@ int GetHotspotPointY(int hotspot) {
 
 int GetHotspotIDAtScreen(int scrx, int scry) {
 	VpPoint vpt = _GP(play).ScreenToRoomDivDown(scrx, scry);
-	if (vpt.second < 0) return 0;
-	return get_hotspot_at(vpt.first.X, vpt.first.Y);
+	if (vpt.second < 0)
+		return 0;
+	Point pt = vpt.first;
+	if ((pt.X >= _GP(thisroom).Width) | (pt.X < 0) | (pt.Y < 0) | (pt.Y >= _GP(thisroom).Height))
+		return 0;
+	return get_hotspot_at(pt.X, pt.Y);
 }
 
 void GetHotspotName(int hotspot, char *buffer) {
diff --git a/engines/ags/engine/ac/global_hotspot.h b/engines/ags/engine/ac/global_hotspot.h
index b4b800b758..207a152cb5 100644
--- a/engines/ags/engine/ac/global_hotspot.h
+++ b/engines/ags/engine/ac/global_hotspot.h
@@ -29,8 +29,6 @@ void DisableHotspot(int hsnum);
 void EnableHotspot(int hsnum);
 int  GetHotspotPointX(int hotspot);
 int  GetHotspotPointY(int hotspot);
-// Gets hotspot ID at the given screen coordinates;
-// if hotspot is disabled or non-existing, returns 0 (no area)
 int  GetHotspotIDAtScreen(int xxx, int yyy);
 void GetHotspotName(int hotspot, char *buffer);
 void RunHotspotInteraction(int hotspothere, int mood);
diff --git a/engines/ags/engine/ac/global_invwindow.cpp b/engines/ags/engine/ac/global_inv_window.cpp
similarity index 86%
rename from engines/ags/engine/ac/global_invwindow.cpp
rename to engines/ags/engine/ac/global_inv_window.cpp
index 8bf556f4a2..a963bb594e 100644
--- a/engines/ags/engine/ac/global_invwindow.cpp
+++ b/engines/ags/engine/ac/global_inv_window.cpp
@@ -20,16 +20,19 @@
  *
  */
 
-#include "ags/engine/ac/gamestate.h"
-#include "ags/engine/ac/global_invwindow.h"
+#include "ags/engine/ac/game_state.h"
+#include "ags/engine/ac/global_inv_window.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/properties.h"
-#include "ags/shared/gui/guiinv.h"
-#include "ags/engine/script/executingscript.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/shared/gui/gui_inv.h"
+#include "ags/engine/script/executing_script.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
 
+using namespace AGS::Shared;
+
 void sc_invscreen() {
 	_G(curscript)->queue_action(ePSAInvScreen, 0, "InventoryScreen");
 }
@@ -44,7 +47,6 @@ void SetInvDimensions(int ww, int hh) {
 		_GP(guiinv)[i].ItemHeight = hh;
 		_GP(guiinv)[i].OnResized();
 	}
-	_G(guis_need_update) = 1;
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/global_invwindow.h b/engines/ags/engine/ac/global_inv_window.h
similarity index 92%
rename from engines/ags/engine/ac/global_invwindow.h
rename to engines/ags/engine/ac/global_inv_window.h
index ad79a6c6f3..13f5bd8808 100644
--- a/engines/ags/engine/ac/global_invwindow.h
+++ b/engines/ags/engine/ac/global_inv_window.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBAL_INVWINDOW_H
-#define AGS_ENGINE_AC_GLOBAL_INVWINDOW_H
+#ifndef AGS_ENGINE_AC_GLOBAL_INV_WINDOW_H
+#define AGS_ENGINE_AC_GLOBAL_INV_WINDOW_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_inventoryitem.cpp b/engines/ags/engine/ac/global_inventory_item.cpp
similarity index 91%
rename from engines/ags/engine/ac/global_inventoryitem.cpp
rename to engines/ags/engine/ac/global_inventory_item.cpp
index 86899580f8..83b5dbebeb 100644
--- a/engines/ags/engine/ac/global_inventoryitem.cpp
+++ b/engines/ags/engine/ac/global_inventory_item.cpp
@@ -21,19 +21,18 @@
  */
 
 #include "ags/shared/ac/common.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/global_gui.h"
-#include "ags/engine/ac/global_inventoryitem.h"
+#include "ags/engine/ac/global_inventory_item.h"
 #include "ags/engine/ac/global_translation.h"
-#include "ags/engine/ac/inventoryitem.h"
-#include "ags/engine/ac/invwindow.h"
+#include "ags/engine/ac/inventory_item.h"
+#include "ags/engine/ac/inv_window.h"
 #include "ags/engine/ac/properties.h"
 #include "ags/engine/ac/string.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/shared/gui/guiinv.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/shared/gui/gui_inv.h"
 #include "ags/engine/ac/event.h"
-#include "ags/engine/ac/gamestate.h"
-#include "ags/globals.h"
+#include "ags/engine/ac/game_state.h"
 
 namespace AGS3 {
 
@@ -53,7 +52,7 @@ void set_inv_item_pic(int invi, int piccy) {
 	}
 
 	_GP(game).invinfo[invi].pic = piccy;
-	_G(guis_need_update) = 1;
+	GUI::MarkInventoryForUpdate(-1, false);
 }
 
 void SetInvItemName(int invi, const char *newName) {
@@ -65,7 +64,7 @@ void SetInvItemName(int invi, const char *newName) {
 	_GP(game).invinfo[invi].name[24] = 0;
 
 	// might need to redraw the GUI if it has the inv item name on it
-	_G(guis_need_update) = 1;
+	GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 }
 
 int GetInvAt(int xxx, int yyy) {
diff --git a/engines/ags/engine/ac/global_inventoryitem.h b/engines/ags/engine/ac/global_inventory_item.h
similarity index 93%
rename from engines/ags/engine/ac/global_inventoryitem.h
rename to engines/ags/engine/ac/global_inventory_item.h
index 11c6b9ccfa..839d21a9f7 100644
--- a/engines/ags/engine/ac/global_inventoryitem.h
+++ b/engines/ags/engine/ac/global_inventory_item.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBAL_INVENTORYITEM_H
-#define AGS_ENGINE_AC_GLOBAL_INVENTORYITEM_H
+#ifndef AGS_ENGINE_AC_GLOBAL_INVENTORY_ITEM_H
+#define AGS_ENGINE_AC_GLOBAL_INVENTORY_ITEM_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_label.cpp b/engines/ags/engine/ac/global_label.cpp
index 562d6fd54e..f47c3c730c 100644
--- a/engines/ags/engine/ac/global_label.cpp
+++ b/engines/ags/engine/ac/global_label.cpp
@@ -22,16 +22,17 @@
 
 #include "ags/engine/ac/global_label.h"
 #include "ags/shared/ac/common.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/label.h"
 #include "ags/engine/ac/string.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/globals.h"
+#include "ags/shared/gui/gui_main.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
+
+
 void SetLabelColor(int guin, int objn, int colr) {
 	if ((guin < 0) | (guin >= _GP(game).numgui))
 		quit("!SetLabelColor: invalid GUI number");
diff --git a/engines/ags/engine/ac/global_mouse.cpp b/engines/ags/engine/ac/global_mouse.cpp
index d72f2345c2..4154f7a098 100644
--- a/engines/ags/engine/ac/global_mouse.cpp
+++ b/engines/ags/engine/ac/global_mouse.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "ags/engine/ac/global_mouse.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 15c4bb6649..8657eb1caa 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -27,21 +27,22 @@
 #include "ags/engine/ac/character.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/event.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/object.h"
-#include "ags/engine/ac/objectcache.h"
+#include "ags/engine/ac/object_cache.h"
 #include "ags/engine/ac/properties.h"
-#include "ags/engine/ac/roomobject.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_object.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/ac/string.h"
-#include "ags/engine/ac/viewframe.h"
+#include "ags/engine/ac/view_frame.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/engine/main/game_run.h"
 #include "ags/engine/script/script.h"
-#include "ags/shared/ac/spritecache.h"
-#include "ags/engine/gfx/graphicsdriver.h"
+#include "ags/shared/ac/sprite_cache.h"
+#include "ags/engine/gfx/graphics_driver.h"
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/shared/gfx/gfx_def.h"
 #include "ags/globals.h"
@@ -71,13 +72,13 @@ int GetObjectIDAtRoom(int roomx, int roomy) {
 		int isflipped = 0;
 		int spWidth = game_to_data_coord(_G(objs)[aa].get_width());
 		int spHeight = game_to_data_coord(_G(objs)[aa].get_height());
-		if (_G(objs)[aa].view >= 0)
+		if (_G(objs)[aa].view != (uint16_t)-1)
 			isflipped = _G(views)[_G(objs)[aa].view].loops[_G(objs)[aa].loop].frames[_G(objs)[aa].frame].flags & VFLG_FLIPSPRITE;
 
 		Bitmap *theImage = GetObjectImage(aa, &isflipped);
 
 		if (is_pos_in_sprite(roomx, roomy, xxx, yyy - spHeight, theImage,
-			spWidth, spHeight, isflipped) == FALSE)
+		                     spWidth, spHeight, isflipped) == FALSE)
 			continue;
 
 		int usebasel = _G(objs)[aa].get_baseline();
@@ -92,9 +93,9 @@ int GetObjectIDAtRoom(int roomx, int roomy) {
 
 void SetObjectTint(int obj, int red, int green, int blue, int opacity, int luminance) {
 	if ((red < 0) || (green < 0) || (blue < 0) ||
-		(red > 255) || (green > 255) || (blue > 255) ||
-		(opacity < 0) || (opacity > 100) ||
-		(luminance < 0) || (luminance > 100))
+	        (red > 255) || (green > 255) || (blue > 255) ||
+	        (opacity < 0) || (opacity > 100) ||
+	        (luminance < 0) || (luminance > 100))
 		quit("!SetObjectTint: invalid parameter. R,G,B must be 0-255, opacity & luminance 0-100");
 
 	if (!is_valid_object(obj))
@@ -131,38 +132,60 @@ void SetObjectView(int obn, int vii) {
 	}
 	vii--;
 
-	_G(objs)[obn].view = vii;
+	if (vii > UINT16_MAX) {
+		debug_script_warn("Warning: object's (id %d) view %d is outside of internal range (%d), reset to no view",
+		                  obn, vii + 1, UINT16_MAX + 1);
+		SetObjectGraphic(obn, 0);
+		return;
+	}
+
+	_G(objs)[obn].view = (uint16_t)vii;
 	_G(objs)[obn].frame = 0;
 	if (_G(objs)[obn].loop >= _G(views)[vii].numLoops)
 		_G(objs)[obn].loop = 0;
 	_G(objs)[obn].cycling = 0;
-	_G(objs)[obn].num = _G(views)[vii].loops[0].frames[0].pic;
+	int pic = _G(views)[vii].loops[0].frames[0].pic;
+	_G(objs)[obn].num = Math::InRangeOrDef<uint16_t>(pic, 0);
+	if (pic > UINT16_MAX)
+		debug_script_warn("Warning: object's (id %d) sprite %d is outside of internal range (%d), reset to 0", obn, pic, UINT16_MAX);
 }
 
 void SetObjectFrame(int obn, int viw, int lop, int fra) {
 	if (!is_valid_object(obn)) quit("!SetObjectFrame: invalid object number specified");
 	viw--;
-	if (viw < 0 || viw >= _GP(game).numviews) quitprintf("!SetObjectFrame: invalid view number used (%d, range is 0 - %d)", viw, _GP(game).numviews - 1);
-	if (lop < 0 || lop >= _G(views)[viw].numLoops) quitprintf("!SetObjectFrame: invalid loop number used (%d, range is 0 - %d)", lop, _G(views)[viw].numLoops - 1);
-	// AGS < 3.5.1 let user to pass literally any positive invalid frame value by silently reassigning it to zero...
-	if (_G(loaded_game_file_version) < kGameVersion_351) {
-		if (fra >= _G(views)[viw].loops[lop].numFrames) {
-			debug_script_warn("SetObjectFrame: frame index out of range (%d, must be 0 - %d), set to 0", fra, _G(views)[viw].loops[lop].numFrames - 1);
-			fra = 0;
-		}
+	if (viw >= _GP(game).numviews) quit("!SetObjectFrame: invalid view number used");
+	if (_G(views)[viw].numLoops == 0) quit("!SetObjectFrame: specified view has no loops");
+	if (lop >= _G(views)[viw].numLoops) quit("!SetObjectFrame: invalid loop number used");
+
+	if (viw > UINT16_MAX || lop > UINT16_MAX || fra > UINT16_MAX) {
+		debug_script_warn("Warning: object's (id %d) view/loop/frame (%d/%d/%d) is outside of internal range (%d/%d/%d), reset to no view",
+		                  obn, viw + 1, lop, fra, UINT16_MAX + 1, UINT16_MAX, UINT16_MAX);
+		SetObjectGraphic(obn, 0);
+		return;
 	}
-	if (fra < 0 || fra >= _G(views)[viw].loops[lop].numFrames) quitprintf("!SetObjectFrame: invalid frame number used (%d, range is 0 - %d)", fra, _G(views)[viw].loops[lop].numFrames - 1);
+
+	_G(objs)[obn].view = (uint16_t)viw;
+	if (lop >= 0)
+		_G(objs)[obn].loop = (uint16_t)lop;
+	if (fra >= 0)
+		_G(objs)[obn].frame = (uint16_t)fra;
+	if (_G(objs)[obn].loop >= _G(views)[viw].numLoops)
+		_G(objs)[obn].loop = 0;
+	if (_G(objs)[obn].frame >= _G(views)[viw].loops[_G(objs)[obn].loop].numFrames)
+		_G(objs)[obn].frame = 0;
+
 	// AGS >= 3.2.0 do not let assign an empty loop
 	// NOTE: pre-3.2.0 games are converting views from ViewStruct272 struct, always has at least 1 frame
 	if (_G(loaded_game_file_version) >= kGameVersion_320) {
-		if (_G(views)[viw].loops[lop].numFrames == 0)
+		if (_G(views)[viw].loops[_G(objs)[obn].loop].numFrames == 0)
 			quit("!SetObjectFrame: specified loop has no frames");
 	}
-	_G(objs)[obn].view = viw;
-	_G(objs)[obn].loop = lop;
-	_G(objs)[obn].frame = fra;
+
 	_G(objs)[obn].cycling = 0;
-	_G(objs)[obn].num = _G(views)[viw].loops[lop].frames[fra].pic;
+	int pic = _G(views)[viw].loops[_G(objs)[obn].loop].frames[_G(objs)[obn].frame].pic;
+	_G(objs)[obn].num = Math::InRangeOrDef<uint16_t>(pic, 0);
+	if (pic > UINT16_MAX)
+		debug_script_warn("Warning: object's (id %d) sprite %d is outside of internal range (%d), reset to 0", obn, pic, UINT16_MAX);
 	CheckViewFrame(viw, _G(objs)[obn].loop, _G(objs)[obn].frame);
 }
 
@@ -201,7 +224,7 @@ void AnimateObjectImpl(int obn, int loopn, int spdd, int rept, int direction, in
 	}
 	if (!is_valid_object(obn))
 		quit("!AnimateObject: invalid object number specified");
-	if (_G(objs)[obn].view < 0)
+	if (_G(objs)[obn].view == (uint16_t)-1)
 		quit("!AnimateObject: object has not been assigned a view");
 	if (loopn < 0 || loopn >= _G(views)[_G(objs)[obn].view].numLoops)
 		quit("!AnimateObject: invalid loop number specified");
@@ -214,21 +237,30 @@ void AnimateObjectImpl(int obn, int loopn, int spdd, int rept, int direction, in
 	if (_G(views)[_G(objs)[obn].view].loops[loopn].numFrames < 1)
 		quit("!AnimateObject: no frames in the specified view loop");
 
-	debug_script_log("Obj %d start anim view %d loop %d, speed %d, repeat %d, frame %d", obn, _G(objs)[obn].view + 1, loopn, spdd, rept, sframe);
-
-	_G(objs)[obn].cycling = rept + 1 + (direction * 10);
-	_G(objs)[obn].loop = loopn;
 	// reverse animation starts at the *previous frame*
 	if (direction) {
 		sframe--;
 		if (sframe < 0)
 			sframe = _G(views)[_G(objs)[obn].view].loops[loopn].numFrames - (-sframe);
 	}
-	_G(objs)[obn].frame = sframe;
 
+	if (loopn > UINT16_MAX || sframe > UINT16_MAX) {
+		debug_script_warn("Warning: object's (id %d) loop/frame (%d/%d) is outside of internal range (%d/%d), cancel animation",
+		                  obn, loopn, sframe, UINT16_MAX, UINT16_MAX);
+		return;
+	}
+
+	debug_script_log("Obj %d start anim view %d loop %d, speed %d, repeat %d, frame %d", obn, _G(objs)[obn].view + 1, loopn, spdd, rept, sframe);
+
+	_G(objs)[obn].cycling = rept + 1 + (direction * 10);
+	_G(objs)[obn].loop = (uint16_t)loopn;
+	_G(objs)[obn].frame = (uint16_t)sframe;
 	_G(objs)[obn].overall_speed = spdd;
 	_G(objs)[obn].wait = spdd + _G(views)[_G(objs)[obn].view].loops[loopn].frames[_G(objs)[obn].frame].speed;
-	_G(objs)[obn].num = _G(views)[_G(objs)[obn].view].loops[loopn].frames[_G(objs)[obn].frame].pic;
+	int pic = _G(views)[_G(objs)[obn].view].loops[loopn].frames[_G(objs)[obn].frame].pic;
+	_G(objs)[obn].num = Math::InRangeOrDef<uint16_t>(pic, 0);
+	if (pic > UINT16_MAX)
+		debug_script_warn("Warning: object's (id %d) sprite %d is outside of internal range (%d), reset to 0", obn, pic, UINT16_MAX);
 	CheckViewFrame(_G(objs)[obn].view, loopn, _G(objs)[obn].frame);
 
 	if (blocking)
@@ -308,13 +340,15 @@ void SetObjectGraphic(int obn, int slott) {
 	if (!is_valid_object(obn)) quit("!SetObjectGraphic: invalid object specified");
 
 	if (_G(objs)[obn].num != slott) {
-		_G(objs)[obn].num = slott;
+		_G(objs)[obn].num = Math::InRangeOrDef<uint16_t>(slott, 0);
+		if (slott > UINT16_MAX)
+			debug_script_warn("Warning: object's (id %d) sprite %d is outside of internal range (%d), reset to 0", obn, slott, UINT16_MAX);
 		debug_script_log("Object %d graphic changed to slot %d", obn, slott);
 	}
 	_G(objs)[obn].cycling = 0;
 	_G(objs)[obn].frame = 0;
 	_G(objs)[obn].loop = 0;
-	_G(objs)[obn].view = -1;
+	_G(objs)[obn].view = (uint16_t)-1;
 }
 
 int GetObjectGraphic(int obn) {
@@ -414,7 +448,7 @@ void RunObjectInteraction(int aa, int mood) {
 			if (run_interaction_event(&_G(croom)->intrObject[aa], passon, 4, (passon == 3)))
 				return;
 		}
-		run_interaction_event(&_G(croom)->intrObject[aa], 4); // any click on obj
+		run_interaction_event(&_G(croom)->intrObject[aa], 4);  // any click on obj
 	}
 }
 
@@ -459,7 +493,7 @@ int AreThingsOverlapping(int thing1, int thing2) {
 		return 0;
 
 	if ((r1.x2 > r2.x1) && (r1.x1 < r2.x2) &&
-		(r1.y2 > r2.y1) && (r1.y1 < r2.y2)) {
+	        (r1.y2 > r2.y1) && (r1.y1 < r2.y2)) {
 		// determine how far apart they are
 		// take the smaller of the X distances as the overlapping amount
 		int xdist = abs(r1.x2 - r2.x1);
@@ -499,6 +533,7 @@ Bitmap *GetObjectImage(int obj, int *isFlipped) {
 			return _G(actsps)[obj];
 		}
 	}
+
 	return _GP(spriteset)[_G(objs)[obj].num];
 }
 
diff --git a/engines/ags/engine/ac/global_object.h b/engines/ags/engine/ac/global_object.h
index 7304322662..cb135fd59b 100644
--- a/engines/ags/engine/ac/global_object.h
+++ b/engines/ags/engine/ac/global_object.h
@@ -20,16 +20,16 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBAL_OBJECT_H
-#define AGS_ENGINE_AC_GLOBAL_OBJECT_H
+#ifndef AGS_ENGINE_AC_GLOBALOBJECT_H
+#define AGS_ENGINE_AC_GLOBALOBJECT_H
 
 namespace AGS3 {
+
 namespace AGS {
 namespace Shared {
 class Bitmap;
-} // namespace Shared
-} // namespace AGS
-
+}
+}
 using namespace AGS; // FIXME later
 
 // TODO: merge with other Rect declared in bitmap unit
diff --git a/engines/ags/engine/ac/global_overlay.cpp b/engines/ags/engine/ac/global_overlay.cpp
index 30fb81ba79..c57244db04 100644
--- a/engines/ags/engine/ac/global_overlay.cpp
+++ b/engines/ags/engine/ac/global_overlay.cpp
@@ -24,25 +24,23 @@
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/display.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/runtime_defines.h"
-#include "ags/engine/ac/screenoverlay.h"
+#include "ags/engine/ac/screen_overlay.h"
 #include "ags/engine/ac/string.h"
-#include "ags/shared/ac/spritecache.h"
+#include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/ac/system.h"
 #include "ags/shared/gfx/bitmap.h"
-#include "ags/globals.h"
+#include "ags/shared/util/wgt2_allg.h"
 
 namespace AGS3 {
 
 using namespace Shared;
 using namespace Engine;
 
-
-
 void RemoveOverlay(int ovrid) {
 	if (find_overlay_of_type(ovrid) < 0) quit("!RemoveOverlay: invalid overlay id passed");
 	remove_screen_overlay(ovrid);
@@ -71,7 +69,7 @@ int CreateTextOverlay(int xx, int yy, int wii, int fontid, int text_color, const
 	if (xx != OVR_AUTOPLACE) {
 		data_to_game_coords(&xx, &yy);
 		wii = data_to_game_coord(wii);
-	} else // allow DisplaySpeechBackground to be shrunk
+	} else  // allow DisplaySpeechBackground to be shrunk
 		allowShrink = 1;
 
 	return CreateTextOverlayCore(xx, yy, wii, fontid, text_color, text, disp_type, allowShrink);
diff --git a/engines/ags/engine/ac/global_overlay.h b/engines/ags/engine/ac/global_overlay.h
index 2b11c972cf..16fe00db39 100644
--- a/engines/ags/engine/ac/global_overlay.h
+++ b/engines/ags/engine/ac/global_overlay.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBALOVERLAY_H
-#define AGS_ENGINE_AC_GLOBALOVERLAY_H
+#ifndef AGS_ENGINE_AC_GLOBAL_OVERLAY_H
+#define AGS_ENGINE_AC_GLOBAL_OVERLAY_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_palette.cpp b/engines/ags/engine/ac/global_palette.cpp
index 5ad19da5de..ada060f373 100644
--- a/engines/ags/engine/ac/global_palette.cpp
+++ b/engines/ags/engine/ac/global_palette.cpp
@@ -22,13 +22,18 @@
 
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_palette.h"
-#include "ags/globals.h"
+#include "ags/shared/util/wgt2_allg.h"
 
 namespace AGS3 {
 
+
+
+
+
+
 void CyclePalette(int strt, int eend) {
 	// hi-color game must invalidate screen since the palette changes
 	// the effect of the drawing operations
diff --git a/engines/ags/engine/ac/global_parser.cpp b/engines/ags/engine/ac/global_parser.cpp
index e21d4794e2..6de4349701 100644
--- a/engines/ags/engine/ac/global_parser.cpp
+++ b/engines/ags/engine/ac/global_parser.cpp
@@ -22,7 +22,7 @@
 
 #include "ags/engine/ac/global_parser.h"
 #include "ags/shared/ac/common.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/string.h"
 #include "ags/globals.h"
 
diff --git a/engines/ags/engine/ac/global_parser.h b/engines/ags/engine/ac/global_parser.h
index 522b871dd1..9c66d05293 100644
--- a/engines/ags/engine/ac/global_parser.h
+++ b/engines/ags/engine/ac/global_parser.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBAL_PARSER_H
-#define AGS_ENGINE_AC_GLOBAL_PARSER_H
+#ifndef AGS_ENGINE_AC_GLOBALPARSER_H
+#define AGS_ENGINE_AC_GLOBALPARSER_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_region.cpp b/engines/ags/engine/ac/global_region.cpp
index f18fefae6c..0f6a4d5312 100644
--- a/engines/ags/engine/ac/global_region.cpp
+++ b/engines/ags/engine/ac/global_region.cpp
@@ -23,11 +23,12 @@
 #include "ags/engine/ac/global_region.h"
 #include "ags/shared/ac/common.h"
 #include "ags/shared/ac/game_version.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/region.h"
 #include "ags/engine/ac/room.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/shared/game/roomstruct.h"
+#include "ags/shared/game/room_struct.h"
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/engine/script/script.h"
 #include "ags/globals.h"
@@ -55,8 +56,15 @@ int GetRegionIDAtRoom(int xxx, int yyy) {
 	}
 
 	int hsthere = _GP(thisroom).RegionMask->GetPixel(xxx, yyy);
-	if (hsthere <= 0 || hsthere >= MAX_ROOM_REGIONS) return 0;
-	if (_G(croom)->region_enabled[hsthere] == 0) return 0;
+	if (hsthere < 0)
+		hsthere = 0;
+
+	if (hsthere >= MAX_ROOM_REGIONS) {
+		quitprintf("!An invalid pixel was found on the room region mask (colour %d, location: %d, %d)", hsthere, xxx, yyy);
+	}
+
+	if (_G(croom)->region_enabled[hsthere] == 0)
+		return 0;
 	return hsthere;
 }
 
@@ -76,7 +84,7 @@ void SetRegionTint(int area, int red, int green, int blue, int amount, int lumin
 		quit("!SetRegionTint: invalid region");
 
 	if ((red < 0) || (red > 255) || (green < 0) || (green > 255) ||
-		(blue < 0) || (blue > 255)) {
+	        (blue < 0) || (blue > 255)) {
 		quit("!SetRegionTint: RGB values must be 0-255");
 	}
 
@@ -97,9 +105,9 @@ void SetRegionTint(int area, int red, int green, int blue, int amount, int lumin
 	blue -= 100;*/
 
 	_GP(thisroom).Regions[area].Tint = (red & 0xFF) |
-		((green & 0xFF) << 8) |
-		((blue & 0XFF) << 16) |
-		((amount & 0xFF) << 24);
+	                                   ((green & 0xFF) << 8) |
+	                                   ((blue & 0XFF) << 16) |
+	                                   ((amount & 0xFF) << 24);
 	_GP(thisroom).Regions[area].Light = (luminance * 25) / 10;
 }
 
diff --git a/engines/ags/engine/ac/global_region.h b/engines/ags/engine/ac/global_region.h
index 93fec2cb0c..f10fc9bcd3 100644
--- a/engines/ags/engine/ac/global_region.h
+++ b/engines/ags/engine/ac/global_region.h
@@ -25,8 +25,6 @@
 
 namespace AGS3 {
 
-// Gets region ID at the given room coordinates;
-// if region is disabled or non-existing, returns 0 (no area)
 int  GetRegionIDAtRoom(int xxx, int yyy);
 void SetAreaLightLevel(int area, int brightness);
 void SetRegionTint(int area, int red, int green, int blue, int amount, int luminance = 100);
diff --git a/engines/ags/engine/ac/global_room.cpp b/engines/ags/engine/ac/global_room.cpp
index 02793bf22f..94cb027351 100644
--- a/engines/ags/engine/ac/global_room.cpp
+++ b/engines/ags/engine/ac/global_room.cpp
@@ -23,17 +23,17 @@
 #include "ags/engine/ac/global_room.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/character.h"
-#include "ags/shared/ac/characterinfo.h"
+#include "ags/shared/ac/character_info.h"
 #include "ags/engine/ac/draw.h"
 #include "ags/engine/ac/event.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_character.h"
 #include "ags/engine/ac/global_game.h"
-#include "ags/engine/ac/movelist.h"
+#include "ags/engine/ac/move_list.h"
 #include "ags/engine/ac/properties.h"
 #include "ags/engine/ac/room.h"
-#include "ags/engine/ac/roomstatus.h"
+#include "ags/engine/ac/room_status.h"
 #include "ags/engine/debugging/debug_log.h"
 #include "ags/engine/debugging/debugger.h"
 #include "ags/engine/script/script.h"
@@ -46,12 +46,12 @@ using namespace Shared;
 
 void SetAmbientTint(int red, int green, int blue, int opacity, int luminance) {
 	if ((red < 0) || (green < 0) || (blue < 0) ||
-		(red > 255) || (green > 255) || (blue > 255) ||
-		(opacity < 0) || (opacity > 100) ||
-		(luminance < 0) || (luminance > 100))
+	        (red > 255) || (green > 255) || (blue > 255) ||
+	        (opacity < 0) || (opacity > 100) ||
+	        (luminance < 0) || (luminance > 100))
 		quit("!SetTint: invalid parameter. R,G,B must be 0-255, opacity & luminance 0-100");
 
-	debug_script_log("Set ambient tint RGB(%d,%d,%d) %d%%", red, green, blue, opacity);
+	debug_script_log("Set _GP(ambient) tint RGB(%d,%d,%d) %d%%", red, green, blue, opacity);
 
 	_GP(play).rtint_enabled = opacity > 0;
 	_GP(play).rtint_red = red;
@@ -90,7 +90,7 @@ void NewRoom(int nrnum) {
 			_GP(play).stop_dialog_at_end = DIALOG_NEWROOM + nrnum;
 		else {
 			quitprintf("!NewRoom: two NewRoom/RunDialog/StopDialog requests within dialog; last was called in \"%s\", line %d",
-				_GP(last_in_dialog_request_script_pos).Section.GetCStr(), _GP(last_in_dialog_request_script_pos).Line);
+			           _GP(last_in_dialog_request_script_pos).Section.GetCStr(), _GP(last_in_dialog_request_script_pos).Line);
 		}
 		return;
 	}
diff --git a/engines/ags/engine/ac/global_screen.cpp b/engines/ags/engine/ac/global_screen.cpp
index 3e38b1697d..ae9cc34157 100644
--- a/engines/ags/engine/ac/global_screen.cpp
+++ b/engines/ags/engine/ac/global_screen.cpp
@@ -21,26 +21,34 @@
  */
 
 #include "ags/shared/ac/common.h"
-#include "ags/engine/ac/gamesetup.h"
+#include "ags/engine/ac/game_setup.h"
 #include "ags/engine/ac/draw.h"
-#include "ags/engine/ac/gamesetup.h"
-#include "ags/shared/ac/gamesetupstruct.h"
-#include "ags/engine/ac/gamestate.h"
+#include "ags/engine/ac/game_setup.h"
+#include "ags/shared/ac/game_setup_struct.h"
+#include "ags/engine/ac/game_state.h"
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/global_screen.h"
 #include "ags/engine/ac/runtime_defines.h"
 #include "ags/engine/ac/screen.h"
 #include "ags/engine/debugging/debug_log.h"
-#include "ags/engine/platform/base/agsplatformdriver.h"
-#include "ags/engine/gfx/graphicsdriver.h"
+#include "ags/engine/platform/base/ags_platform_driver.h"
+#include "ags/engine/gfx/graphics_driver.h"
 #include "ags/shared/gfx/bitmap.h"
-#include "ags/globals.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 using namespace AGS::Engine;
 
+
+
+
+
+
+
+
+
+
 void FlipScreen(int amount) {
 	if ((amount < 0) | (amount > 3)) quit("!FlipScreen: invalid argument (0-3)");
 	_GP(play).screen_flipped = amount;
@@ -158,7 +166,7 @@ void SetNextScreenTransition(int newtrans) {
 
 void SetFadeColor(int red, int green, int blue) {
 	if ((red < 0) || (red > 255) || (green < 0) || (green > 255) ||
-		(blue < 0) || (blue > 255))
+	        (blue < 0) || (blue > 255))
 		quit("!SetFadeColor: Red, Green and Blue must be 0-255");
 
 	_GP(play).fade_to_red = red;
diff --git a/engines/ags/engine/ac/global_screen.h b/engines/ags/engine/ac/global_screen.h
index feeb90dcc5..25b7f1e3ae 100644
--- a/engines/ags/engine/ac/global_screen.h
+++ b/engines/ags/engine/ac/global_screen.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef AGS_ENGINE_AC_GLOBAL_SCREEN_H
-#define AGS_ENGINE_AC_GLOBAL_SCREEN_H
+#ifndef AGS_ENGINE_AC_GLOBALSCREEN_H
+#define AGS_ENGINE_AC_GLOBALSCREEN_H
 
 namespace AGS3 {
 
diff --git a/engines/ags/engine/ac/global_slider.cpp b/engines/ags/engine/ac/global_slider.cpp
index 4d6a73df84..bc89199412 100644
--- a/engines/ags/engine/ac/global_slider.cpp
+++ b/engines/ags/engine/ac/global_slider.cpp
@@ -22,16 +22,17 @@
 
 #include "ags/engine/ac/global_slider.h"
 #include "ags/shared/ac/common.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/slider.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/shared/gui/guislider.h"
-#include "ags/globals.h"
+#include "ags/shared/gui/gui_main.h"
+#include "ags/shared/gui/gui_slider.h"
 
 namespace AGS3 {
 
 using namespace AGS::Shared;
 
+
+
 void SetSliderValue(int guin, int objn, int valn) {
 	if ((guin < 0) | (guin >= _GP(game).numgui)) quit("!SetSliderValue: invalid GUI number");
 	if (_GP(guis)[guin].GetControlType(objn) != kGUISlider)
diff --git a/engines/ags/engine/ac/global_textbox.cpp b/engines/ags/engine/ac/global_textbox.cpp
index adbd211b9d..b0e71e6af1 100644
--- a/engines/ags/engine/ac/global_textbox.cpp
+++ b/engines/ags/engine/ac/global_textbox.cpp
@@ -22,12 +22,11 @@
 
 #include "ags/engine/ac/global_textbox.h"
 #include "ags/shared/ac/common.h"
-#include "ags/shared/ac/gamesetupstruct.h"
+#include "ags/shared/ac/game_setup_struct.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/ac/textbox.h"
-#include "ags/shared/gui/guimain.h"
-#include "ags/shared/gui/guitextbox.h"
-#include "ags/globals.h"


Commit: b104d788884f248d2969586d8294feac22bdbb3e
    https://github.com/scummvm/scummvm/commit/b104d788884f248d2969586d8294feac22bdbb3e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:50-07:00

Commit Message:
AGS: Enabling disabled blocks, and making ScummVM needed changes

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/dynobj/script_overlay.cpp
    engines/ags/engine/ac/global_character.cpp
    engines/ags/engine/ac/global_overlay.cpp
    engines/ags/engine/ac/overlay.cpp
    engines/ags/engine/ac/route_finder.cpp
    engines/ags/engine/ac/timer.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/game/savegame_v321.cpp
    engines/ags/engine/gfx/ali_3d_scummvm.cpp
    engines/ags/engine/gfx/ali_3d_scummvm.h
    engines/ags/engine/main/config.cpp
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/update.cpp
    engines/ags/engine/platform/base/sys_main.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/shared/core/asset_manager.cpp
    engines/ags/shared/core/asset_manager.h
    engines/ags/shared/font/ttf_font_renderer.cpp
    engines/ags/shared/util/buffered_stream.cpp
    engines/ags/shared/util/string.cpp


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index ce14504554..e089f95dc6 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -717,7 +717,7 @@ ScriptOverlay *Character_SayBackground(CharacterInfo *chaa, const char *texx) {
 	scOver->borderWidth = 0;
 	scOver->isBackgroundSpeech = 1;
 	int handl = ccRegisterManagedObject(scOver, scOver);
-	_GP(screenover)[ovri].associatedOverlayHandle = handl;
+	_G(screenover)[ovri].associatedOverlayHandle = handl;
 
 	return scOver;
 }
@@ -2268,8 +2268,8 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 	if (_GP(play).bgspeech_stay_on_display == 0) {
 		// remove any background speech
 		for (aa = 0; aa < _G(numscreenover); aa++) {
-			if (_GP(screenover)[aa].timeout > 0) {
-				remove_screen_overlay(_GP(screenover)[aa].type);
+			if (_G(screenover)[aa].timeout > 0) {
+				remove_screen_overlay(_G(screenover)[aa].type);
 				aa--;
 			}
 		}
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 045ab4047c..dda4726bfa 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -238,7 +238,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 	// we should not delete text_window_ds here, because it is now owned by Overlay
 
 	if (disp_type >= DISPLAYTEXT_NORMALOVERLAY) {
-		return _GP(screenover)[nse].type;
+		return _G(screenover)[nse].type;
 	}
 
 	//
@@ -316,10 +316,10 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 			_GP(play).messagetime = 2;
 
 		if (!overlayPositionFixed) {
-			_GP(screenover)[nse].positionRelativeToScreen = false;
-			VpPoint vpt = _GP(play).GetRoomViewport(0)->ScreenToRoom(_GP(screenover)[nse].x, _GP(screenover)[nse].y, false);
-			_GP(screenover)[nse].x = vpt.first.X;
-			_GP(screenover)[nse].y = vpt.first.Y;
+			_G(screenover)[nse].positionRelativeToScreen = false;
+			VpPoint vpt = _GP(play).GetRoomViewport(0)->ScreenToRoom(_G(screenover)[nse].x, _G(screenover)[nse].y, false);
+			_G(screenover)[nse].x = vpt.first.X;
+			_G(screenover)[nse].y = vpt.first.Y;
 		}
 
 		GameLoopUntilNoOverlay();
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 2e49f6c053..ea8099c3a1 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1870,12 +1870,12 @@ void draw_gui_and_overlays() {
 	// draw overlays, except text boxes and portraits
 	for (gg = 0; gg < _G(numscreenover); gg++) {
 		// complete overlay draw in non-transparent mode
-		if (_GP(screenover)[gg].type == OVER_COMPLETE)
-			add_thing_to_draw(_GP(screenover)[gg].bmp, _GP(screenover)[gg].x, _GP(screenover)[gg].y, TRANS_OPAQUE, false);
-		else if (_GP(screenover)[gg].type != OVER_TEXTMSG && _GP(screenover)[gg].type != OVER_PICTURE) {
+		if (_G(screenover)[gg].type == OVER_COMPLETE)
+			add_thing_to_draw(_G(screenover)[gg].bmp, _G(screenover)[gg].x, _G(screenover)[gg].y, TRANS_OPAQUE, false);
+		else if (_G(screenover)[gg].type != OVER_TEXTMSG && _G(screenover)[gg].type != OVER_PICTURE) {
 			int tdxp, tdyp;
-			get_overlay_position(_GP(screenover)[gg], &tdxp, &tdyp);
-			add_thing_to_draw(_GP(screenover)[gg].bmp, tdxp, tdyp, 0, _GP(screenover)[gg].hasAlphaChannel);
+			get_overlay_position(_G(screenover)[gg], &tdxp, &tdyp);
+			add_thing_to_draw(_G(screenover)[gg].bmp, tdxp, tdyp, 0, _G(screenover)[gg].hasAlphaChannel);
 		}
 	}
 
@@ -1953,10 +1953,10 @@ void draw_gui_and_overlays() {
 
 	// draw speech and portraits (so that they appear over GUIs)
 	for (gg = 0; gg < _G(numscreenover); gg++) {
-		if (_GP(screenover)[gg].type == OVER_TEXTMSG || _GP(screenover)[gg].type == OVER_PICTURE) {
+		if (_G(screenover)[gg].type == OVER_TEXTMSG || _G(screenover)[gg].type == OVER_PICTURE) {
 			int tdxp, tdyp;
-			get_overlay_position(_GP(screenover)[gg], &tdxp, &tdyp);
-			add_thing_to_draw(_GP(screenover)[gg].bmp, tdxp, tdyp, 0, false);
+			get_overlay_position(_G(screenover)[gg], &tdxp, &tdyp);
+			add_thing_to_draw(_G(screenover)[gg].bmp, tdxp, tdyp, 0, false);
 		}
 	}
 
diff --git a/engines/ags/engine/ac/dynobj/script_overlay.cpp b/engines/ags/engine/ac/dynobj/script_overlay.cpp
index 443cb5f3d6..1053a60c4d 100644
--- a/engines/ags/engine/ac/dynobj/script_overlay.cpp
+++ b/engines/ags/engine/ac/dynobj/script_overlay.cpp
@@ -35,7 +35,7 @@ int ScriptOverlay::Dispose(const char *address, bool force) {
 	// with that handle later
 	int overlayIndex = find_overlay_of_type(overlayId);
 	if (overlayIndex >= 0) {
-		_GP(screenover)[overlayIndex].associatedOverlayHandle = 0;
+		_G(screenover)[overlayIndex].associatedOverlayHandle = 0;
 	}
 
 	// if this is being removed voluntarily (ie. pointer out of
diff --git a/engines/ags/engine/ac/global_character.cpp b/engines/ags/engine/ac/global_character.cpp
index 4ca5965849..1e58ffd41f 100644
--- a/engines/ags/engine/ac/global_character.cpp
+++ b/engines/ags/engine/ac/global_character.cpp
@@ -549,7 +549,7 @@ int DisplaySpeechBackground(int charid, const char *speel) {
 	// remove any previous background speech for this character
 	int cc;
 	for (cc = 0; cc < _G(numscreenover); cc++) {
-		if (_GP(screenover)[cc].bgSpeechForChar == charid) {
+		if (_G(screenover)[cc].bgSpeechForChar == charid) {
 			remove_screen_overlay_index(cc);
 			cc--;
 		}
@@ -559,8 +559,8 @@ int DisplaySpeechBackground(int charid, const char *speel) {
 	                             -_GP(game).chars[charid].talkcolor, get_translation(speel), DISPLAYTEXT_NORMALOVERLAY);
 
 	int scid = find_overlay_of_type(ovrl);
-	_GP(screenover)[scid].bgSpeechForChar = charid;
-	_GP(screenover)[scid].timeout = GetTextDisplayTime(speel, 1);
+	_G(screenover)[scid].bgSpeechForChar = charid;
+	_G(screenover)[scid].timeout = GetTextDisplayTime(speel, 1);
 	return ovrl;
 }
 
diff --git a/engines/ags/engine/ac/global_overlay.cpp b/engines/ags/engine/ac/global_overlay.cpp
index c57244db04..bcb261d90d 100644
--- a/engines/ags/engine/ac/global_overlay.cpp
+++ b/engines/ags/engine/ac/global_overlay.cpp
@@ -53,7 +53,7 @@ int CreateGraphicOverlay(int xx, int yy, int slott, int trans) {
 	wputblock(screeno, 0, 0, _GP(spriteset)[slott], trans);
 	bool hasAlpha = (_GP(game).SpriteInfos[slott].Flags & SPF_ALPHACHANNEL) != 0;
 	int nse = add_screen_overlay(xx, yy, OVER_CUSTOM, screeno, hasAlpha);
-	return _GP(screenover)[nse].type;
+	return _G(screenover)[nse].type;
 }
 
 int CreateTextOverlayCore(int xx, int yy, int wii, int fontid, int text_color, const char *text, int disp_type, int allowShrink) {
@@ -87,8 +87,8 @@ void MoveOverlay(int ovrid, int newx, int newy) {
 
 	int ovri = find_overlay_of_type(ovrid);
 	if (ovri < 0) quit("!MoveOverlay: invalid overlay ID specified");
-	_GP(screenover)[ovri].x = newx;
-	_GP(screenover)[ovri].y = newy;
+	_G(screenover)[ovri].x = newx;
+	_G(screenover)[ovri].y = newy;
 }
 
 int IsOverlayValid(int ovrid) {
diff --git a/engines/ags/engine/ac/overlay.cpp b/engines/ags/engine/ac/overlay.cpp
index 39c394906e..76111ee1dc 100644
--- a/engines/ags/engine/ac/overlay.cpp
+++ b/engines/ags/engine/ac/overlay.cpp
@@ -55,8 +55,8 @@ void Overlay_SetText(ScriptOverlay *scover, int wii, int fontid, int text_color,
 	int ovri = find_overlay_of_type(scover->overlayId);
 	if (ovri < 0)
 		quit("!Overlay.SetText: invalid overlay ID specified");
-	int xx = game_to_data_coord(_GP(screenover)[ovri].x) - scover->borderWidth;
-	int yy = game_to_data_coord(_GP(screenover)[ovri].y) - scover->borderHeight;
+	int xx = game_to_data_coord(_G(screenover)[ovri].x) - scover->borderWidth;
+	int yy = game_to_data_coord(_G(screenover)[ovri].y) - scover->borderHeight;
 
 	RemoveOverlay(scover->overlayId);
 	const int disp_type = scover->overlayId;
@@ -71,7 +71,7 @@ int Overlay_GetX(ScriptOverlay *scover) {
 		quit("!invalid overlay ID specified");
 
 	int tdxp, tdyp;
-	get_overlay_position(_GP(screenover)[ovri], &tdxp, &tdyp);
+	get_overlay_position(_G(screenover)[ovri], &tdxp, &tdyp);
 
 	return game_to_data_coord(tdxp);
 }
@@ -81,7 +81,7 @@ void Overlay_SetX(ScriptOverlay *scover, int newx) {
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
 
-	_GP(screenover)[ovri].x = data_to_game_coord(newx);
+	_G(screenover)[ovri].x = data_to_game_coord(newx);
 }
 
 int Overlay_GetY(ScriptOverlay *scover) {
@@ -90,7 +90,7 @@ int Overlay_GetY(ScriptOverlay *scover) {
 		quit("!invalid overlay ID specified");
 
 	int tdxp, tdyp;
-	get_overlay_position(_GP(screenover)[ovri], &tdxp, &tdyp);
+	get_overlay_position(_G(screenover)[ovri], &tdxp, &tdyp);
 
 	return game_to_data_coord(tdyp);
 }
@@ -100,7 +100,7 @@ void Overlay_SetY(ScriptOverlay *scover, int newy) {
 	if (ovri < 0)
 		quit("!invalid overlay ID specified");
 
-	_GP(screenover)[ovri].y = data_to_game_coord(newy);
+	_G(screenover)[ovri].y = data_to_game_coord(newy);
 }
 
 int Overlay_GetValid(ScriptOverlay *scover) {
@@ -135,8 +135,8 @@ ScriptOverlay *Overlay_CreateTextual(int x, int y, int width, int font, int colo
 	sco->overlayId = CreateTextOverlayCore(x, y, width, font, colour, text, DISPLAYTEXT_NORMALOVERLAY, 0);
 
 	int ovri = find_overlay_of_type(sco->overlayId);
-	sco->borderWidth = game_to_data_coord(_GP(screenover)[ovri].x - x);
-	sco->borderHeight = game_to_data_coord(_GP(screenover)[ovri].y - y);
+	sco->borderWidth = game_to_data_coord(_G(screenover)[ovri].x - x);
+	sco->borderHeight = game_to_data_coord(_G(screenover)[ovri].y - y);
 	sco->isBackgroundSpeech = 0;
 
 	ccRegisterManagedObject(sco, sco);
@@ -158,13 +158,13 @@ void dispose_overlay(ScreenOverlay &over) {
 }
 
 void remove_screen_overlay_index(int over_idx) {
-	ScreenOverlay &over = _GP(screenover)[over_idx];
+	ScreenOverlay &over = _G(screenover)[over_idx];
 	dispose_overlay(over);
 	if (over.type == OVER_COMPLETE) _G(is_complete_overlay)--;
 	if (over.type == OVER_TEXTMSG) _G(is_text_overlay)--;
 	_G(numscreenover)--;
 	for (int i = over_idx; i < _G(numscreenover); ++i)
-		_GP(screenover)[i] = _GP(screenover)[i + 1];
+		_G(screenover)[i] = _G(screenover)[i + 1];
 	// if an overlay before the sierra-style speech one is removed,
 	// update the index
 	if (_G(face_talking) > over_idx)
@@ -173,7 +173,7 @@ void remove_screen_overlay_index(int over_idx) {
 
 void remove_screen_overlay(int type) {
 	for (int i = 0; i < _G(numscreenover);) {
-		if (type < 0 || _GP(screenover)[i].type == type)
+		if (type < 0 || _G(screenover)[i].type == type)
 			remove_screen_overlay_index(i);
 		else
 			i++;
@@ -182,7 +182,7 @@ void remove_screen_overlay(int type) {
 
 int find_overlay_of_type(int type) {
 	for (int i = 0; i < _G(numscreenover); ++i) {
-		if (_GP(screenover)[i].type == type) return i;
+		if (_G(screenover)[i].type == type) return i;
 	}
 	return -1;
 }
@@ -203,7 +203,7 @@ int add_screen_overlay(int x, int y, int type, Shared::Bitmap *piccy, int pic_of
 			}
 		}
 	}
-	ScreenOverlay &over = _GP(screenover)[_G(numscreenover)++];
+	ScreenOverlay &over = _G(screenover)[_G(numscreenover)++];
 	over.pic = piccy;
 	over.bmp = _G(gfxDriver)->CreateDDBFromBitmap(piccy, alphaChannel);
 	over.x = x;
@@ -265,12 +265,12 @@ void get_overlay_position(const ScreenOverlay &over, int *x, int *y) {
 
 void recreate_overlay_ddbs() {
 	for (int i = 0; i < _G(numscreenover); ++i) {
-		if (_GP(screenover)[i].bmp)
-			_G(gfxDriver)->DestroyDDB(_GP(screenover)[i].bmp);
-		if (_GP(screenover)[i].pic)
-			_GP(screenover)[i].bmp = _G(gfxDriver)->CreateDDBFromBitmap(_GP(screenover)[i].pic, false);
+		if (_G(screenover)[i].bmp)
+			_G(gfxDriver)->DestroyDDB(_G(screenover)[i].bmp);
+		if (_G(screenover)[i].pic)
+			_G(screenover)[i].bmp = _G(gfxDriver)->CreateDDBFromBitmap(_G(screenover)[i].pic, false);
 		else
-			_GP(screenover)[i].bmp = nullptr;
+			_G(screenover)[i].bmp = nullptr;
 	}
 }
 
diff --git a/engines/ags/engine/ac/route_finder.cpp b/engines/ags/engine/ac/route_finder.cpp
index 4da257b4c9..6503eadbf5 100644
--- a/engines/ags/engine/ac/route_finder.cpp
+++ b/engines/ags/engine/ac/route_finder.cpp
@@ -119,7 +119,8 @@ void init_pathfinder(GameDataVersion game_file_version) {
 }
 
 void shutdown_pathfinder() {
-	route_finder_impl->shutdown_pathfinder();
+	if (route_finder_impl)
+		route_finder_impl->shutdown_pathfinder();
 }
 
 void set_wallscreen(Bitmap *wallscreen) {
diff --git a/engines/ags/engine/ac/timer.cpp b/engines/ags/engine/ac/timer.cpp
index 139ce8433d..94e02567b5 100644
--- a/engines/ags/engine/ac/timer.cpp
+++ b/engines/ags/engine/ac/timer.cpp
@@ -24,6 +24,7 @@
 #include "ags/engine/ac/timer.h"
 #include "ags/shared/core/platform.h"
 #include "ags/engine/platform/base/ags_platform_driver.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -66,12 +67,14 @@ void WaitForNextFrame() {
 		_G(next_frame_timestamp) = now;
 	}
 
-	auto frame_time_remaining = _G(next_frame_timestamp) - now;
-	if (frame_time_remaining > std::chrono::milliseconds::zero()) {
+	if (_G(next_frame_timestamp) > now) {
+		auto frame_time_remaining = _G(next_frame_timestamp) - now;
 		std::this_thread::sleep_for(frame_time_remaining);
 	}
 
 	_G(next_frame_timestamp) += frameDuration;
+
+	::AGS::g_vm->_rawScreen->update();
 }
 
 void skipMissedTicks() {
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 1348160cce..86a17bdde9 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -749,8 +749,8 @@ HSaveError ReadDynamicSprites(Stream *in, int32_t cmp_ver, const PreservedParams
 HSaveError WriteOverlays(Stream *out) {
 	out->WriteInt32(_G(numscreenover));
 	for (int i = 0; i < _G(numscreenover); ++i) {
-		_GP(screenover)[i].WriteToFile(out);
-		serialize_bitmap(_GP(screenover)[i].pic, out);
+		_G(screenover)[i].WriteToFile(out);
+		serialize_bitmap(_G(screenover)[i].pic, out);
 	}
 	return HSaveError::None();
 }
@@ -762,9 +762,9 @@ HSaveError ReadOverlays(Stream *in, int32_t cmp_ver, const PreservedParams &pp,
 		return err;
 	_G(numscreenover) = over_count;
 	for (int i = 0; i < _G(numscreenover); ++i) {
-		_GP(screenover)[i].ReadFromFile(in, cmp_ver);
-		if (_GP(screenover)[i].hasSerializedBitmap)
-			_GP(screenover)[i].pic = read_serialized_bitmap(in);
+		_G(screenover)[i].ReadFromFile(in, cmp_ver);
+		if (_G(screenover)[i].hasSerializedBitmap)
+			_G(screenover)[i].pic = read_serialized_bitmap(in);
 	}
 	return err;
 }
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 66d8259929..18c917e56a 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -271,7 +271,7 @@ static void restore_game_ambientsounds(Stream *in, RestoredData &r_data) {
 static void ReadOverlays_Aligned(Stream *in) {
 	AlignedStream align_s(in, Shared::kAligned_Read);
 	for (int i = 0; i < _G(numscreenover); ++i) {
-		_GP(screenover)[i].ReadFromFile(&align_s, 0);
+		_G(screenover)[i].ReadFromFile(&align_s, 0);
 		align_s.Reset();
 	}
 }
@@ -280,8 +280,8 @@ static void restore_game_overlays(Stream *in) {
 	_G(numscreenover) = in->ReadInt32();
 	ReadOverlays_Aligned(in);
 	for (int bb = 0; bb < _G(numscreenover); bb++) {
-		if (_GP(screenover)[bb].hasSerializedBitmap)
-			_GP(screenover)[bb].pic = read_serialized_bitmap(in);
+		if (_G(screenover)[bb].hasSerializedBitmap)
+			_G(screenover)[bb].pic = read_serialized_bitmap(in);
 	}
 }
 
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 6566e94f02..50f609e9f2 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -29,6 +29,7 @@
 #include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/engine/platform/base/sys_main.h"
 #include "ags/engine/ac/timer.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -111,36 +112,9 @@ bool ScummVMRendererGraphicsDriver::SetDisplayMode(const DisplayMode &mode) {
 	if (!IsModeSupported(mode))
 		return false;
 
-	if (sys_get_window() == nullptr) {
-#ifdef TODO
-		SDL_Window *window = sys_window_create("", mode.Width, mode.Height, mode.Windowed);
-
-		_hasGamma = SDL_GetWindowGammaRamp(window, _defaultGammaRed, _defaultGammaGreen, _defaultGammaBlue) == 0;
-
-		uint32 rendererFlags = SDL_RENDERER_ACCELERATED;
-		if (mode.Vsync) {
-			rendererFlags |= SDL_RENDERER_PRESENTVSYNC;
-		}
-		_renderer = SDL_CreateRenderer(window, -1, rendererFlags);
-
-		SDL_RendererInfo rinfo{};
-		if (SDL_GetRendererInfo(_renderer, &rinfo) == 0) {
-			Debug::Printf("Created Renderer: %s", rinfo.name);
-			Debug::Printf("Available texture formats:");
-			for (int i = 0; i < rinfo.num_texture_formats; i++) {
-				Debug::Printf("\t- %s", SDL_GetPixelFormatName(rinfo.texture_formats[i]));
-			}
-		}
-#endif
-	} else {
-		sys_window_set_style(mode.Windowed);
-		if (mode.Windowed)
-			sys_window_set_size(mode.Width, mode.Height, true);
-	}
-
-#if AGS_PLATFORM_OS_ANDROID
-	SDL_RenderSetLogicalSize(_renderer, mode.Width, mode.Height);
-#endif
+	const int driver = mode.Windowed ? GFX_SCUMMVM : GFX_SCUMMVM_FULLSCREEN;
+	if (set_gfx_mode(driver, mode.Width, mode.Height, 0, 0) != 0)
+		return false;
 
 	OnInit();
 	OnModeSet(mode);
@@ -436,44 +410,14 @@ void ScummVMRendererGraphicsDriver::RenderSpriteBatch(const ALSpriteBatch &batch
 }
 
 void ScummVMRendererGraphicsDriver::BlitToTexture() {
-#ifdef TODO
-	void *pixels = nullptr;
-	int pitch = 0;
-	auto res = SDL_LockTexture(_screenTex, NULL, &pixels, &pitch);
-	if (res != 0) {
-		return;
-	}
-
-	// Because the virtual screen may be of any color depth,
-	// we wrap texture pixels in a fake bitmap here and call
-	// standard blit operation, for simplicity sake.
-	const int vwidth = virtualScreen->GetWidth();
-	const int vheight = virtualScreen->GetHeight();
-	if ((_lastTexPixels != pixels) || (_lastTexPitch != pitch)) {
-		_fakeTexBitmap->dat = pixels;
-		auto p = (unsigned char *)pixels;
-		for (int i = 0; i < vheight; i++) {
-			_fakeTexBitmap->line[i] = p;
-			p += pitch;
-		}
-		_lastTexPixels = (unsigned char *)pixels;
-		_lastTexPitch = pitch;
-	}
-
-	blit(virtualScreen->GetAllegroBitmap(), _fakeTexBitmap, 0, 0, 0, 0, vwidth, vheight);
-
-	SDL_UnlockTexture(_screenTex);
-#endif
+	::AGS::g_vm->_screen->getSurface().blitFrom(
+		virtualScreen->GetAllegroBitmap()->getSurface());
 }
 
 void ScummVMRendererGraphicsDriver::Present() {
-#ifdef TODO
-	if (!_renderer) {
-		return;
-	}
-
 	BlitToTexture();
 
+#if DEPRECATED
 	SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);
 	SDL_SetRenderDrawColor(_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
 	SDL_RenderFillRect(_renderer, nullptr);
@@ -490,25 +434,23 @@ void ScummVMRendererGraphicsDriver::Present() {
 }
 
 void ScummVMRendererGraphicsDriver::Render(int /*xoff*/, int /*yoff*/, GlobalFlipType flip) {
-#ifdef TODO
 	switch (flip) {
 	case kFlip_Both:
-		_renderFlip = (SDL_RendererFlip)(SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL);
+		_renderFlip = (RendererFlip)(FLIP_HORIZONTAL | FLIP_VERTICAL);
 		break;
 	case kFlip_Horizontal:
-		_renderFlip = SDL_FLIP_HORIZONTAL;
+		_renderFlip = FLIP_HORIZONTAL;
 		break;
 	case kFlip_Vertical:
-		_renderFlip = SDL_FLIP_VERTICAL;
+		_renderFlip = FLIP_VERTICAL;
 		break;
 	default:
-		_renderFlip = SDL_FLIP_NONE;
+		_renderFlip = FLIP_NONE;
 		break;
 	}
 
 	RenderToBackBuffer();
 	Present();
-#endif
 }
 
 void ScummVMRendererGraphicsDriver::Render() {
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.h b/engines/ags/engine/gfx/ali_3d_scummvm.h
index 93547e36aa..5ee3a2ea3d 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.h
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.h
@@ -52,6 +52,12 @@ class ScummVMRendererGraphicsDriver;
 class ScummVMRendererGfxFilter;
 using AGS::Shared::Bitmap;
 
+enum RendererFlip {
+	FLIP_NONE = 0x00000000,       /**< Do not flip */
+	FLIP_HORIZONTAL = 0x00000001, /**< flip horizontally */
+	FLIP_VERTICAL = 0x00000002    /**< flip vertically */
+};
+
 class ALSoftwareBitmap : public IDriverDependantBitmap {
 public:
 	// NOTE by CJ:
@@ -234,8 +240,8 @@ private:
 	uint16 _defaultGammaGreen[256] {};
 	uint16 _defaultGammaBlue[256] {};
 
-	/*    SDL_RendererFlip _renderFlip = SDL_FLIP_NONE;
-	    SDL_Renderer *_renderer = nullptr;
+	RendererFlip _renderFlip = FLIP_NONE;
+	/*  SDL_Renderer *_renderer = nullptr;
 	    SDL_Texture *_screenTex = nullptr; */
 	// BITMAP struct for wrapping screen texture locked pixels, so that we may use blit()
 	BITMAP *_fakeTexBitmap = nullptr;
diff --git a/engines/ags/engine/main/config.cpp b/engines/ags/engine/main/config.cpp
index 741cdb6c92..bdcd1beadd 100644
--- a/engines/ags/engine/main/config.cpp
+++ b/engines/ags/engine/main/config.cpp
@@ -225,7 +225,7 @@ void read_legacy_graphics_config(const ConfigTree &cfg) {
 		_GP(usetup).override_upscale = true; // run low-res game in high-res mode
 	}
 
-	_GP(usetup).Screen.DisplayMode.Windowed = INIreadint(cfg, "misc", "windowed") > 0;
+	_GP(usetup).Screen.DisplayMode.Windowed = true; // INIreadint(cfg, "misc", "windowed") > 0;
 	_GP(usetup).Screen.DriverID = INIreadstring(cfg, "misc", "gfxdriver", _GP(usetup).Screen.DriverID);
 
 	{
@@ -324,7 +324,7 @@ void apply_config(const ConfigTree &cfg) {
 		// Graphics mode
 		_GP(usetup).Screen.DriverID = INIreadstring(cfg, "graphics", "driver", _GP(usetup).Screen.DriverID);
 
-		_GP(usetup).Screen.DisplayMode.Windowed = INIreadint(cfg, "graphics", "windowed") > 0;
+		_GP(usetup).Screen.DisplayMode.Windowed = true; // INIreadint(cfg, "graphics", "windowed") > 0;
 		_GP(usetup).Screen.DisplayMode.ScreenSize.SizeDef = _GP(usetup).Screen.DisplayMode.Windowed ? kScreenDef_ByGameScaling : kScreenDef_MaxDisplay;
 		_GP(usetup).Screen.DisplayMode.ScreenSize.SizeDef = parse_screendef(INIreadstring(cfg, "graphics", "screen_def"),
 		        _GP(usetup).Screen.DisplayMode.ScreenSize.SizeDef);
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 1bf3e6135f..6b74f25ed9 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -413,22 +413,6 @@ void engine_init_debug() {
 	}
 }
 
-void atexit_handler() {
-	if (_G(proper_exit) == 0) {
-		_G(platform)->DisplayAlert("Error: the program has exited without requesting it.\n"
-		                           "Program pointer: %+03d  (write this number down), ACI version %s\n"
-		                           "If you see a list of numbers above, please write them down and contact\n"
-		                           "developers. Otherwise, note down any other information displayed.",
-		                           _G(our_eip), _G(EngineVersion).LongString.GetCStr());
-	}
-}
-
-void engine_init_exit_handler() {
-	Debug::Printf(kDbgMsg_Info, "Install exit handler");
-
-	atexit(atexit_handler);
-}
-
 void engine_init_rand() {
 	_GP(play).randseed = g_system->getMillis();
 	::AGS::g_vm->setRandomNumberSeed(_GP(play).randseed);
@@ -500,7 +484,9 @@ extern char android_base_directory[256];
 
 // TODO: remake/remove this nonsense
 int check_write_access() {
-
+#if AGS_PLATFORM_SCUMMVM
+	return true;
+#else
 	if (_G(platform)->GetDiskFreeSpaceMB() < 2)
 		return 0;
 
@@ -538,6 +524,7 @@ int check_write_access() {
 		return 0;
 
 	return 1;
+#endif
 }
 
 int engine_check_disk_space() {
@@ -1206,8 +1193,6 @@ int initialize_engine(const ConfigTree &startup_opts) {
 
 	_G(our_eip) = -10;
 
-	engine_init_exit_handler();
-
 	engine_init_rand();
 
 	engine_init_pathfinder();
diff --git a/engines/ags/engine/main/update.cpp b/engines/ags/engine/main/update.cpp
index e6634c5b12..2572b2a1a7 100644
--- a/engines/ags/engine/main/update.cpp
+++ b/engines/ags/engine/main/update.cpp
@@ -223,10 +223,10 @@ void update_following_exactly_characters(int &numSheep, int *followingAsSheep) {
 void update_overlay_timers() {
 	// update overlay timers
 	for (int aa = 0; aa < _G(numscreenover); aa++) {
-		if (_GP(screenover)[aa].timeout > 0) {
-			_GP(screenover)[aa].timeout--;
-			if (_GP(screenover)[aa].timeout == 0)
-				remove_screen_overlay(_GP(screenover)[aa].type);
+		if (_G(screenover)[aa].timeout > 0) {
+			_G(screenover)[aa].timeout--;
+			if (_G(screenover)[aa].timeout == 0)
+				remove_screen_overlay(_G(screenover)[aa].type);
 		}
 	}
 }
@@ -390,14 +390,14 @@ void update_sierra_speech() {
 				if (_G(facetalk_qfg4_override_placement_y)) {
 					view_frame_y = _GP(play).speech_portrait_y;
 				} else {
-					view_frame_y = (_GP(screenover)[_G(face_talking)].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
+					view_frame_y = (_G(screenover)[_G(face_talking)].pic->GetHeight() / 2) - (_GP(game).SpriteInfos[thisPic].Height / 2);
 				}
-				_GP(screenover)[_G(face_talking)].pic->Clear(0);
+				_G(screenover)[_G(face_talking)].pic->Clear(0);
 			} else {
-				_GP(screenover)[_G(face_talking)].pic->ClearTransparent();
+				_G(screenover)[_G(face_talking)].pic->ClearTransparent();
 			}
 
-			Bitmap *frame_pic = _GP(screenover)[_G(face_talking)].pic;
+			Bitmap *frame_pic = _G(screenover)[_G(face_talking)].pic;
 			const ViewFrame *face_vf = &_G(views)[_G(facetalkview)].loops[_G(facetalkloop)].frames[_G(facetalkframe)];
 			bool face_has_alpha = (_GP(game).SpriteInfos[face_vf->pic].Flags & SPF_ALPHACHANNEL) != 0;
 			DrawViewFrame(frame_pic, face_vf, view_frame_x, view_frame_y);
@@ -409,7 +409,7 @@ void update_sierra_speech() {
 				DrawViewFrame(frame_pic, blink_vf, view_frame_x, view_frame_y, face_has_alpha);
 			}
 
-			_G(gfxDriver)->UpdateDDBFromBitmap(_GP(screenover)[_G(face_talking)].bmp, _GP(screenover)[_G(face_talking)].pic, face_has_alpha);
+			_G(gfxDriver)->UpdateDDBFromBitmap(_G(screenover)[_G(face_talking)].bmp, _G(screenover)[_G(face_talking)].pic, face_has_alpha);
 		}  // end if updatedFrame
 	}
 }
diff --git a/engines/ags/engine/platform/base/sys_main.cpp b/engines/ags/engine/platform/base/sys_main.cpp
index 7f136b9596..74bb4a980f 100644
--- a/engines/ags/engine/platform/base/sys_main.cpp
+++ b/engines/ags/engine/platform/base/sys_main.cpp
@@ -54,10 +54,8 @@ const int DEFAULT_DISPLAY_INDEX = 0; // TODO: is this always right?
 int sys_get_desktop_resolution(int &width, int &height) {
 	// TODO: ScummVM has a hardcoded dummy desktop resolution. See if there's any
 	// need to change the values, given we're hardcoded for pretend full-screen
-	if (width)
-		width = 640;
-	if (height)
-		height = 480;
+	width = 1000;
+	height = 1000;
 
 	return 0;
 }
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 96058f0de4..8a9f85e320 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -283,7 +283,7 @@ Globals::Globals() {
 	_mouse = new Mouse();
 
 	// overlay.cpp globals
-	_screenover = new std::vector<ScreenOverlay>();
+	_screenover = new ScreenOverlay[MAX_SCREEN_OVERLAYS];
 
 	// plugin_object_reader.cpp globals
 	_pluginReaders = new PluginObjectReader[MAX_PLUGIN_OBJECT_READERS];
@@ -499,7 +499,7 @@ Globals::~Globals() {
 	delete _mouse;
 
 	// overlay.cpp globals
-	delete _screenover;
+	delete[] _screenover;
 
 	// plugin_object_reader.cpp globals
 	delete[] _pluginReaders;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 81c48eb0fb..c49544dbd4 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -1130,7 +1130,7 @@ public:
 	 * @{
 	 */
 
-	std::vector<ScreenOverlay> *_screenover;
+	ScreenOverlay *_screenover;
 	int _is_complete_overlay = 0, _is_text_overlay = 0;
 	int _numscreenover = 0;
 
diff --git a/engines/ags/shared/core/asset_manager.cpp b/engines/ags/shared/core/asset_manager.cpp
index 4ea2fc1b6c..b410a845b7 100644
--- a/engines/ags/shared/core/asset_manager.cpp
+++ b/engines/ags/shared/core/asset_manager.cpp
@@ -85,11 +85,8 @@ AssetManager::AssetManager() {
 
 void AssetManager::SetSearchPriority(AssetSearchPriority priority) {
 	_libsByPriority.Priority = kAssetPriorityDir;
-#ifdef TODO
+
 	std::sort(_activeLibs.begin(), _activeLibs.end(), _libsByPriority);
-#else
-	error("TODO: std::sort");
-#endif
 }
 
 AssetSearchPriority AssetManager::GetSearchPriority() const {
@@ -109,7 +106,7 @@ AssetError AssetManager::AddLibrary(const String &path, const String &filters, c
 			// already present, only assign new filters
 			lib->Filters = filters.Split(',');
 			if (out_lib)
-				*out_lib = lib.get();
+				*out_lib = lib;
 			return kAssetNoError;
 		}
 	}
@@ -142,6 +139,9 @@ void AssetManager::RemoveLibrary(const String &path) {
 }
 
 void AssetManager::RemoveAllLibraries() {
+	for (uint i = 0; i < _libs.size(); ++i)
+		delete _libs[i];
+
 	_libs.clear();
 	_activeLibs.clear();
 }
@@ -151,7 +151,7 @@ size_t AssetManager::GetLibraryCount() const {
 }
 
 const AssetLibInfo *AssetManager::GetLibraryInfo(size_t index) const {
-	return index < _libs.size() ? _libs[index].get() : nullptr;
+	return index < _libs.size() ? _libs[index] : nullptr;
 }
 
 bool AssetManager::DoesAssetExist(const String &asset_name, const String &filter) const {
@@ -194,12 +194,9 @@ AssetError AssetManager::RegisterAssetLib(const String &path, AssetLibEx *&out_l
 		lib->LibFileNames[0] = lib->BaseFileName;
 	}
 
-	out_lib = lib.get();
-#ifdef TODO
-	_libs.push_back(std::move(lib));
-#else
-	error("TODO: std::move");
-#endif
+	out_lib = lib.release();
+	_libs.push_back(out_lib);
+
 	return kAssetNoError;
 }
 
diff --git a/engines/ags/shared/core/asset_manager.h b/engines/ags/shared/core/asset_manager.h
index 74ce04e534..3d9b776c1e 100644
--- a/engines/ags/shared/core/asset_manager.h
+++ b/engines/ags/shared/core/asset_manager.h
@@ -76,7 +76,9 @@ struct AssetLocation {
 class AssetManager {
 public:
 	AssetManager();
-	~AssetManager() {}
+	~AssetManager() {
+		RemoveAllLibraries();
+	}
 
 	// Test if given file is main data file
 	static bool         IsDataFile(const String &data_file);
@@ -126,12 +128,13 @@ private:
 	bool        GetAssetFromLib(const AssetLibInfo *lib, const String &asset_name, AssetLocation *loc, Shared::FileOpenMode open_mode, Shared::FileWorkMode work_mode) const;
 	bool        GetAssetFromDir(const AssetLibInfo *lib, const String &asset_name, AssetLocation *loc, Shared::FileOpenMode open_mode, Shared::FileWorkMode work_mode) const;
 
-	std::vector<std::unique_ptr<AssetLibEx>> _libs;
+	std::vector<AssetLibEx *> _libs;
 	std::vector<AssetLibEx *> _activeLibs;
 
-	struct LibsByPriority : public std::binary_function<const AssetLibInfo *, const AssetLibInfo *, bool> {
+	struct LibsByPriority {
 		AssetSearchPriority Priority = kAssetPriorityDir;
-		bool operator()(const AssetLibInfo *, const AssetLibInfo *) const;
+
+		bool operator()(const AssetLibInfo *x, const AssetLibInfo *y) const;
 	} _libsByPriority;
 };
 
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index ef6ece4796..67fd420001 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -104,10 +104,11 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize, const FontRen
 	delete reader;
 
 	ALFONT_FONT *alfptr = alfont_load_font_from_mem(membuffer, lenof);
-	free(membuffer);
 
-	if (alfptr == nullptr)
+	if (alfptr == nullptr) {
+		free(membuffer);
 		return false;
+	}
 
 	// TODO: move this somewhere, should not be right here
 #if AGS_OUTLINE_FONT_FIX
diff --git a/engines/ags/shared/util/buffered_stream.cpp b/engines/ags/shared/util/buffered_stream.cpp
index 200782b2a5..e609cca905 100644
--- a/engines/ags/shared/util/buffered_stream.cpp
+++ b/engines/ags/shared/util/buffered_stream.cpp
@@ -32,18 +32,19 @@ namespace Shared {
 
 BufferedStream::BufferedStream(const String &file_name, FileOpenMode open_mode, FileWorkMode work_mode, DataEndianess stream_endianess)
 	: FileStream(file_name, open_mode, work_mode, stream_endianess), _buffer(BufferStreamSize), _bufferPosition(0), _position(0) {
-	if (FileStream::Seek(0, kSeekEnd) == false)
-		error("Error determining stream end.");
+	if (IsValid()) {
+		if (FileStream::Seek(0, kSeekEnd) == false)
+			error("Error determining stream end.");
 
-	_end = FileStream::GetPosition();
-	if (_end == -1)
-		error("Error determining stream end.");
+		_end = FileStream::GetPosition();
+		if (_end == -1)
+			error("Error determining stream end.");
 
-	if (FileStream::Seek(0, kSeekBegin) == false)
-		error("Error determining stream end.");
+		if (FileStream::Seek(0, kSeekBegin) == false)
+			error("Error determining stream end.");
+	}
 
 	_buffer.resize(0);
-
 }
 
 void BufferedStream::FillBufferFromPosition(soff_t position) {
diff --git a/engines/ags/shared/util/string.cpp b/engines/ags/shared/util/string.cpp
index 3137b56eb7..7fb36065ec 100644
--- a/engines/ags/shared/util/string.cpp
+++ b/engines/ags/shared/util/string.cpp
@@ -362,11 +362,11 @@ String String::Section(char separator, size_t first, size_t last,
 
 std::vector<String> String::Split(char separator) const {
 	std::vector<String> result;
-	if (!_cstr || !separator)
+	if (!separator)
 		return result;
 
 	const char *ptr = _cstr;
-	while (*ptr) {
+	while (ptr && *ptr) {
 		const char *found_cstr = strchr(ptr, separator);
 		if (!found_cstr) break;
 		result.push_back(String(ptr, found_cstr - ptr));


Commit: a4569cb180d11edead179605148dc87e6f9d0198
    https://github.com/scummvm/scummvm/commit/a4569cb180d11edead179605148dc87e6f9d0198
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:51-07:00

Commit Message:
AGS: Properly remove sound caching

Changed paths:
  R engines/ags/engine/media/audio/sound_cache.cpp
  R engines/ags/engine/media/audio/sound_cache.h
    engines/ags/engine/media/audio/audio_system.h
    engines/ags/engine/media/audio/sound.cpp
    engines/ags/globals.h
    engines/ags/module.mk
    engines/ags/shared/core/asset_manager.cpp
    engines/ags/shared/core/asset_manager.h


diff --git a/engines/ags/engine/media/audio/audio_system.h b/engines/ags/engine/media/audio/audio_system.h
index fb7ff533a2..63906c83d1 100644
--- a/engines/ags/engine/media/audio/audio_system.h
+++ b/engines/ags/engine/media/audio/audio_system.h
@@ -28,8 +28,6 @@
 
 #include "ags/engine/media/audio/audio.h"
 
-#include "ags/engine/media/audio/sound_cache.h"
-
 #include "ags/engine/media/audio/sound_clip.h"
 #include "ags/engine/media/audio/sound.h"
 
diff --git a/engines/ags/engine/media/audio/sound.cpp b/engines/ags/engine/media/audio/sound.cpp
index 4963e724b0..b74be6e350 100644
--- a/engines/ags/engine/media/audio/sound.cpp
+++ b/engines/ags/engine/media/audio/sound.cpp
@@ -28,19 +28,20 @@
 
 #include "ags/engine/media/audio/audio_defines.h"
 #include "ags/engine/media/audio/sound.h"
-#include "ags/engine/media/audio/sound_cache.h"
 #include "ags/engine/media/audio/sound_clip.h"
 #include "ags/engine/media/audio/clip_my_midi.h"
+#include "ags/shared/core/asset_manager.h"
 #include "audio/mods/mod_xm_s3m.h"
 #include "audio/mods/protracker.h"
 #include "audio/decoders/mp3.h"
 #include "audio/decoders/vorbis.h"
 #include "audio/decoders/wave.h"
+#include "ags/globals.h"
 
 namespace AGS3 {
 
 SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, int loop) {
-	Common::SeekableReadStream *data = get_cached_sound(asset_name);
+	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		Audio::AudioStream *audioStream = Audio::makeWAVStream(data, DisposeAfterUse::YES);
 		return new SoundClipWave<MUS_WAVE>(audioStream, voll, loop);
@@ -51,7 +52,7 @@ SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, int loop) {
 
 SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, int voll, bool loop) {
 #ifdef USE_MAD
-	Common::SeekableReadStream *data = get_cached_sound(asset_name);
+	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		Audio::AudioStream *audioStream = Audio::makeMP3Stream(data, DisposeAfterUse::YES);
 		return new SoundClipWave<MUS_MP3>(audioStream, voll, false);
@@ -69,7 +70,7 @@ SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, int voll) {
 
 SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, int voll, bool loop) {
 #ifdef USE_VORBIS
-	Common::SeekableReadStream *data = get_cached_sound(asset_name);
+	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		Audio::AudioStream *audioStream = Audio::makeVorbisStream(data, DisposeAfterUse::YES);
 		return new SoundClipWave<MUS_OGG>(audioStream, voll, loop);
@@ -86,7 +87,7 @@ SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, int voll) {
 }
 
 SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool repeat) {
-	Common::SeekableReadStream *data = get_cached_sound(asset_name);
+	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		return new MYMIDI(data, repeat);
 	} else {
@@ -95,7 +96,7 @@ SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool repeat) {
 }
 
 SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool repeat) {
-	Common::SeekableReadStream *data = get_cached_sound(asset_name);
+	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		// determine the file extension
 		size_t lastDot = asset_name.Filter.FindCharReverse('.');
diff --git a/engines/ags/engine/media/audio/sound_cache.cpp b/engines/ags/engine/media/audio/sound_cache.cpp
deleted file mode 100644
index 5ce6f2047c..0000000000
--- a/engines/ags/engine/media/audio/sound_cache.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/memstream.h"
-#include "ags/engine/ac/file.h"
-#include "ags/shared/util/wgt2_allg.h"
-#include "ags/engine/media/audio/sound_cache.h"
-#include "ags/engine/util/mutex.h"
-#include "ags/engine/util/mutex_lock.h"
-#include "ags/shared/util/string.h"
-#include "ags/shared/debugging/out.h"
-#include "ags/globals.h"
-#include "ags/ags.h"
-
-namespace AGS3 {
-
-using namespace Shared;
-
-void clear_sound_cache() {
-	AGS::Engine::MutexLock _lock(::AGS::g_vm->_soundCacheMutex);
-
-	if (_G(sound_cache_entries)) {
-		int i;
-		for (i = 0; i < _G(psp_audio_cachesize); i++) {
-			if (_G(sound_cache_entries)[i].data) {
-				free(_G(sound_cache_entries)[i].data);
-				_G(sound_cache_entries)[i].data = nullptr;
-				free(_G(sound_cache_entries)[i].file_name);
-				_G(sound_cache_entries)[i].file_name = nullptr;
-				_G(sound_cache_entries)[i].reference = 0;
-			}
-		}
-	} else {
-		_G(sound_cache_entries) = (sound_cache_entry_t *)malloc(_G(psp_audio_cachesize) * sizeof(sound_cache_entry_t));
-		memset(_G(sound_cache_entries), 0, _G(psp_audio_cachesize) * sizeof(sound_cache_entry_t));
-	}
-}
-
-void sound_cache_free(char *buffer) {
-	AGS::Engine::MutexLock _lock(::AGS::g_vm->_soundCacheMutex);
-
-#ifdef SOUND_CACHE_DEBUG
-	Debug::Printf("sound_cache_free(%p)\n", buffer);
-#endif
-	int i;
-	for (i = 0; i < _G(psp_audio_cachesize); i++) {
-		if (_G(sound_cache_entries)[i].data == buffer) {
-			if (_G(sound_cache_entries)[i].reference > 0)
-				_G(sound_cache_entries)[i].reference--;
-
-#ifdef SOUND_CACHE_DEBUG
-			Debug::Printf("..decreased reference count of slot %d to %d\n", i, _G(sound_cache_entries)[i].reference);
-#endif
-			return;
-		}
-	}
-
-#ifdef SOUND_CACHE_DEBUG
-	Debug::Printf("..freeing uncached sound\n");
-#endif
-
-	// Sound is uncached
-	if (i == _G(psp_audio_cachesize)) {
-		free(buffer);
-	}
-}
-
-
-char *get_cached_sound(const AssetPath &asset_name, size_t &size) {
-	AGS::Engine::MutexLock _lock(::AGS::g_vm->_soundCacheMutex);
-
-#ifdef SOUND_CACHE_DEBUG
-	Debug::Printf("get_cached_sound(%s)\n", asset_name.first.GetCStr());
-#endif
-
-	size = 0;
-
-	int i;
-	for (i = 0; i < _G(psp_audio_cachesize); i++) {
-		if (_G(sound_cache_entries)[i].data == nullptr)
-			continue;
-
-		if (strcmp(asset_name.Filter, _G(sound_cache_entries)[i].file_name) == 0) {
-#ifdef SOUND_CACHE_DEBUG
-			Debug::Printf("..found in slot %d\n", i);
-#endif
-			_G(sound_cache_entries)[i].reference++;
-			_G(sound_cache_entries)[i].last_used = _G(sound_cache_counter)++;
-			size = _G(sound_cache_entries)[i].size;
-
-			return _G(sound_cache_entries)[i].data;
-		}
-	}
-
-	// Not found
-	PACKFILE *mp3in = nullptr;
-
-	mp3in = PackfileFromAsset(asset_name, size);
-	if (mp3in == nullptr) {
-		return nullptr;
-	}
-
-	// Find free slot
-	for (i = 0; i < _G(psp_audio_cachesize); i++) {
-		if (_G(sound_cache_entries)[i].data == nullptr)
-			break;
-	}
-
-	// No free slot?
-	if (i == _G(psp_audio_cachesize)) {
-		unsigned int oldest = _G(sound_cache_counter);
-		int index = -1;
-
-		for (i = 0; i < _G(psp_audio_cachesize); i++) {
-			if (_G(sound_cache_entries)[i].reference == 0) {
-				if (_G(sound_cache_entries)[i].last_used < oldest) {
-					oldest = _G(sound_cache_entries)[i].last_used;
-					index = i;
-				}
-			}
-		}
-
-		i = index;
-	}
-
-	// Load new file
-	char *newdata;
-
-	newdata = (char *)malloc(size);
-
-	if (newdata == nullptr) {
-		pack_fclose(mp3in);
-		return nullptr;
-	}
-
-	pack_fread(newdata, size, mp3in);
-	pack_fclose(mp3in);
-
-	if (i == -1) {
-		// No cache slot empty, return uncached data
-#ifdef SOUND_CACHE_DEBUG
-		Debug::Printf("..loading uncached\n");
-#endif
-		return newdata;
-	} else {
-		// Add to cache, free old sound first
-#ifdef SOUND_CACHE_DEBUG
-		Debug::Printf("..loading cached in slot %d\n", i);
-#endif
-
-		if (_G(sound_cache_entries)[i].data) {
-			free(_G(sound_cache_entries)[i].data);
-		}
-
-		_G(sound_cache_entries)[i].size = size;
-		_G(sound_cache_entries)[i].data = newdata;
-
-		if (_G(sound_cache_entries)[i].file_name)
-			free(_G(sound_cache_entries)[i].file_name);
-		_G(sound_cache_entries)[i].file_name = (char *)malloc(strlen(asset_name.Filter) + 1);
-		strcpy(_G(sound_cache_entries)[i].file_name, asset_name.Filter);
-		_G(sound_cache_entries)[i].reference = 1;
-		_G(sound_cache_entries)[i].last_used = _G(sound_cache_counter)++;
-
-		return _G(sound_cache_entries)[i].data;
-	}
-}
-
-Common::SeekableReadStream *get_cached_sound(const AssetPath &asset_name) {
-	size_t muslen = 0;
-	const byte *data = (byte *)get_cached_sound(asset_name, muslen);
-	if (data == nullptr)
-		return nullptr;
-
-	// Create a read stream for the sound
-	return new Common::MemoryReadStream(data, muslen, DisposeAfterUse::NO);
-}
-
-} // namespace AGS3
diff --git a/engines/ags/engine/media/audio/sound_cache.h b/engines/ags/engine/media/audio/sound_cache.h
deleted file mode 100644
index 89f4caf04a..0000000000
--- a/engines/ags/engine/media/audio/sound_cache.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AGS_ENGINE_MEDIA_AUDIO_SOUNDCACHE_H
-#define AGS_ENGINE_MEDIA_AUDIO_SOUNDCACHE_H
-
-#include "ags/engine/ac/asset_helper.h"
-#include "common/stream.h"
-
-namespace AGS3 {
-
-// PSP: A simple sound cache. The size can be configured in the config file.
-// The data rate while reading from disk on the PSP is usually between 500 to 900 kiB/s,
-// caching the last used sound files therefore improves game performance.
-
-//#define SOUND_CACHE_DEBUG
-
-struct sound_cache_entry_t {
-	char *file_name;
-	int number;
-	int free;
-	unsigned int last_used;
-	unsigned int size;
-	char *data;
-	int reference;
-};
-
-void clear_sound_cache();
-void sound_cache_free(char *buffer);
-char *get_cached_sound(const AssetPath &asset_name, size_t &size);
-Common::SeekableReadStream *get_cached_sound(const AssetPath &asset_name);
-
-} // namespace AGS3
-
-#endif
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index c49544dbd4..abd71c0328 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -155,7 +155,6 @@ struct ScriptPosition;
 struct ScriptRegion;
 struct ScriptString;
 struct ScriptSystem;
-struct sound_cache_entry_t;
 struct SOUNDCLIP;
 struct SpeechLipSyncLine;
 struct SpriteListEntry;
@@ -1258,17 +1257,6 @@ public:
 
 	/**@}*/
 
-	/**
-	 * @defgroup agssoundcacheglobals soundcache globals
-	 * @ingroup agsglobals
-	 * @{
-	 */
-
-	sound_cache_entry_t *_sound_cache_entries = nullptr;
-	unsigned int _sound_cache_counter = 0;
-
-	/**@}*/
-
 	/**
 	 * @defgroup agsstringglobals string globals
 	 * @ingroup agsglobals
diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index b58b2dce3f..78ef5d8dfc 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -270,7 +270,6 @@ MODULE_OBJS = \
 	engine/media/audio/clip_my_midi.o \
 	engine/media/audio/queued_audio_item.o \
 	engine/media/audio/sound.o \
-	engine/media/audio/sound_cache.o \
 	engine/media/audio/sound_clip.o \
 	engine/media/video/video.o \
 	engine/platform/base/ags_platform_driver.o \
diff --git a/engines/ags/shared/core/asset_manager.cpp b/engines/ags/shared/core/asset_manager.cpp
index b410a845b7..0287a45ed2 100644
--- a/engines/ags/shared/core/asset_manager.cpp
+++ b/engines/ags/shared/core/asset_manager.cpp
@@ -276,6 +276,17 @@ Stream *AssetManager::OpenAsset(const String &asset_name, const String &filter,
 	return nullptr;
 }
 
+Common::SeekableReadStream *AssetManager::OpenAssetStream(const String &asset_name) const {
+	return OpenAssetStream(asset_name, "");
+}
+
+Common::SeekableReadStream *AssetManager::OpenAssetStream(const String &asset_name, const String &filter) const {
+	Stream *stream = OpenAsset(asset_name, filter);
+	if (!stream)
+		return nullptr;
+
+	return new ScummVMReadStream(stream);
+}
 
 String GetAssetErrorText(AssetError err) {
 	switch (err) {
diff --git a/engines/ags/shared/core/asset_manager.h b/engines/ags/shared/core/asset_manager.h
index 3d9b776c1e..ce1563bd05 100644
--- a/engines/ags/shared/core/asset_manager.h
+++ b/engines/ags/shared/core/asset_manager.h
@@ -36,9 +36,11 @@
 // TODO: return stream as smart pointer.
 //
 //=============================================================================
+
 #ifndef AGS_SHARED_CORE_ASSET_MANAGER_H
 #define AGS_SHARED_CORE_ASSET_MANAGER_H
 
+#include "common/stream.h"
 #include "ags/lib/std/functional.h"
 #include "ags/lib/std/memory.h"
 #include "ags/shared/core/asset.h"
@@ -114,6 +116,11 @@ public:
 	Stream *OpenAsset(const String &asset_name, const String &filter, soff_t *asset_size = nullptr,
 					  FileOpenMode open_mode = kFile_Open,
 					  FileWorkMode work_mode = kFile_Read) const;
+	// Open asset stream in the given work mode; returns null if asset is not found or cannot be opened
+	// This method only searches in libraries that do not have any defined filters
+	Common::SeekableReadStream *OpenAssetStream(const String &asset_name) const;
+	// Open asset stream, providing a single filter to search in matching libraries
+	Common::SeekableReadStream *OpenAssetStream(const String &asset_name, const String &filter) const;
 
 private:
 	struct AssetLibEx : AssetLibInfo {


Commit: 06c5e089fd685808303c7c5f222a22375757e479
    https://github.com/scummvm/scummvm/commit/06c5e089fd685808303c7c5f222a22375757e479
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:51-07:00

Commit Message:
AGS: Hook up event handling

Changed paths:
    engines/ags/engine/ac/sys_events.cpp
    engines/ags/engine/ac/sys_events.h
    engines/ags/engine/main/game_run.cpp
    engines/ags/events.cpp
    engines/ags/events.h
    engines/ags/lib/allegro/keyboard.cpp
    engines/ags/lib/allegro/keyboard.h


diff --git a/engines/ags/engine/ac/sys_events.cpp b/engines/ags/engine/ac/sys_events.cpp
index 8ed20c12b9..03391710f3 100644
--- a/engines/ags/engine/ac/sys_events.cpp
+++ b/engines/ags/engine/ac/sys_events.cpp
@@ -32,6 +32,7 @@
 #include "ags/engine/device/mouse_w32.h"
 #include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/engine/main/engine.h"
+#include "ags/events.h"
 #include "ags/globals.h"
 
 // TODO: Replace me
@@ -58,335 +59,38 @@ static void(*_on_quit_callback)(void) = nullptr;
 static void(*_on_switchin_callback)(void) = nullptr;
 static void(*_on_switchout_callback)(void) = nullptr;
 
-
-// Converts SDL scan and key codes to the ags keycode
-eAGSKeyCode ags_keycode_from_sdl(const SDL_Event &event) {
-#ifdef TODO
-	// Printable ASCII characters are returned only from SDL_TEXTINPUT event,
-	// as it has key presses + mods correctly converted using current system locale already,
-	// so no need to do that manually.
-	// NOTE: keycodes such as SDLK_EXCLAIM ('!') could be misleading, as they are NOT
-	// received when user presses for example Shift + 1 on regular keyboard, but only on
-	// systems where single keypress can produce that symbol.
-	// NOTE: following will not work for Unicode, will need to reimplement whole thing
-	if (_G(event).type == SDL_TEXTINPUT) {
-		unsigned char textch = _G(event).text.text[0];
-		if (textch >= 32 && textch <= 255) {
-			return static_cast<eAGSKeyCode>(textch);
-		}
-		return eAGSKeyCodeNone;
-	}
-
-	if (_G(event).type != SDL_KEYDOWN)
-		return eAGSKeyCodeNone;
-
-	const SDL_Keysym key = _G(event).key.keysym;
-	const SDL_Keycode sym = key.sym;
-	const Uint16 mod = key.mod;
-	// Ctrl and Alt combinations realign the letter code to certain offset
-	if (sym >= SDLK_a && sym <= SDLK_z) {
-		if ((mod & KMOD_CTRL) != 0) // align letters to code 1
-			return static_cast<eAGSKeyCode>(0 + (sym - SDLK_a) + 1);
-		else if ((mod & KMOD_ALT) != 0) // align letters to code 301
-			return static_cast<eAGSKeyCode>(AGS_EXT_KEY_SHIFT + (sym - SDLK_a) + 1);
-	}
-
-	// Remaining codes may match or not, but we use a big table anyway.
-	// TODO: this is code by [sonneveld],
-	// double check that we must use scan codes here, maybe can use sdl key (sym) too?
-	switch (key.scancode) {
-	case SDL_SCANCODE_BACKSPACE:
-		return eAGSKeyCodeBackspace;
-	case SDL_SCANCODE_TAB:
-	case SDL_SCANCODE_KP_TAB:
-		return eAGSKeyCodeTab;
-	case SDL_SCANCODE_RETURN:
-	case SDL_SCANCODE_RETURN2:
-	case SDL_SCANCODE_KP_ENTER:
-		return eAGSKeyCodeReturn;
-	case SDL_SCANCODE_ESCAPE:
-		return eAGSKeyCodeEscape;
-
-	case SDL_SCANCODE_F1:
-		return eAGSKeyCodeF1;
-	case SDL_SCANCODE_F2:
-		return eAGSKeyCodeF2;
-	case SDL_SCANCODE_F3:
-		return eAGSKeyCodeF3;
-	case SDL_SCANCODE_F4:
-		return eAGSKeyCodeF4;
-	case SDL_SCANCODE_F5:
-		return eAGSKeyCodeF5;
-	case SDL_SCANCODE_F6:
-		return eAGSKeyCodeF6;
-	case SDL_SCANCODE_F7:
-		return eAGSKeyCodeF7;
-	case SDL_SCANCODE_F8:
-		return eAGSKeyCodeF8;
-	case SDL_SCANCODE_F9:
-		return eAGSKeyCodeF9;
-	case SDL_SCANCODE_F10:
-		return eAGSKeyCodeF10;
-	case SDL_SCANCODE_F11:
-		return eAGSKeyCodeF11;
-	case SDL_SCANCODE_F12:
-		return eAGSKeyCodeF12;
-
-	case SDL_SCANCODE_KP_7:
-	case SDL_SCANCODE_HOME:
-		return eAGSKeyCodeHome;
-	case SDL_SCANCODE_KP_8:
-	case SDL_SCANCODE_UP:
-		return eAGSKeyCodeUpArrow;
-	case SDL_SCANCODE_KP_9:
-	case SDL_SCANCODE_PAGEUP:
-		return eAGSKeyCodePageUp;
-	case SDL_SCANCODE_KP_4:
-	case SDL_SCANCODE_LEFT:
-		return eAGSKeyCodeLeftArrow;
-	case SDL_SCANCODE_KP_5:
-		return eAGSKeyCodeNumPad5;
-	case SDL_SCANCODE_KP_6:
-	case SDL_SCANCODE_RIGHT:
-		return eAGSKeyCodeRightArrow;
-	case SDL_SCANCODE_KP_1:
-	case SDL_SCANCODE_END:
-		return eAGSKeyCodeEnd;
-	case SDL_SCANCODE_KP_2:
-	case SDL_SCANCODE_DOWN:
-		return eAGSKeyCodeDownArrow;
-	case SDL_SCANCODE_KP_3:
-	case SDL_SCANCODE_PAGEDOWN:
-		return eAGSKeyCodePageDown;
-	case SDL_SCANCODE_KP_0:
-	case SDL_SCANCODE_INSERT:
-		return eAGSKeyCodeInsert;
-	case SDL_SCANCODE_KP_PERIOD:
-	case SDL_SCANCODE_DELETE:
-		return eAGSKeyCodeDelete;
-
-	default:
-		return eAGSKeyCodeNone;
-	}
-#else
-	error("TODO: ags_keycode_from_sdl");
-#endif
-	return eAGSKeyCodeNone;
-}
-
-// Converts ags key to SDL key scans (up to 3 values, because this is not a 1:1 match);
-// NOTE: will ignore Ctrl+ or Alt+ script keys.
-// TODO: double check and ammend later if anything is missing
-bool ags_key_to_sdl_scan(eAGSKeyCode key, SDL_Scancode(&scan)[3]) {
-#ifdef TODO
-	scan[0] = SDL_SCANCODE_UNKNOWN;
-	scan[1] = SDL_SCANCODE_UNKNOWN;
-	scan[2] = SDL_SCANCODE_UNKNOWN;
-	SDL_Keycode sym = SDLK_UNKNOWN;
-
-	// SDL sym codes happen to match small ASCII letters, so lowercase ours if necessary
-	if (key >= eAGSKeyCodeA && key <= eAGSKeyCodeZ) {
-		sym = static_cast<SDL_Keycode>(key - eAGSKeyCodeA + SDLK_a);
-	}
-	// Rest of the printable characters seem to match (and match ascii codes)
-	else if (key >= eAGSKeyCodeSpace && key <= eAGSKeyCodeBackquote) {
-		sym = static_cast<SDL_Keycode>(key);
-	}
-
-	// If we have got key sym, convert it to SDL scancode using library's function
-	if (sym != SDLK_UNKNOWN) {
-		scan[0] = SDL_GetScancodeFromKey(sym);
-		return true;
-	}
-
-	// Other keys are mapped directly to scancode (based on [sonneveld]'s code)
-	switch (key) {
-	case eAGSKeyCodeBackspace:
-		scan[0] = SDL_SCANCODE_BACKSPACE;
-		scan[1] = SDL_SCANCODE_KP_BACKSPACE;
-		return true;
-	case eAGSKeyCodeTab:
-		scan[0] = SDL_SCANCODE_TAB;
-		scan[1] = SDL_SCANCODE_KP_TAB;
-		return true;
-	case eAGSKeyCodeReturn:
-		scan[0] = SDL_SCANCODE_RETURN;
-		scan[1] = SDL_SCANCODE_RETURN2;
-		scan[2] = SDL_SCANCODE_KP_ENTER;
-		return true;
-	case eAGSKeyCodeEscape:
-		scan[0] = SDL_SCANCODE_ESCAPE;
-		return true;
-
-	case eAGSKeyCodeF1:
-		scan[0] = SDL_SCANCODE_F1;
-		return true;
-	case eAGSKeyCodeF2:
-		scan[0] = SDL_SCANCODE_F2;
-		return true;
-	case eAGSKeyCodeF3:
-		scan[0] = SDL_SCANCODE_F3;
-		return true;
-	case eAGSKeyCodeF4:
-		scan[0] = SDL_SCANCODE_F4;
-		return true;
-	case eAGSKeyCodeF5:
-		scan[0] = SDL_SCANCODE_F5;
-		return true;
-	case eAGSKeyCodeF6:
-		scan[0] = SDL_SCANCODE_F6;
-		return true;
-	case eAGSKeyCodeF7:
-		scan[0] = SDL_SCANCODE_F7;
-		return true;
-	case eAGSKeyCodeF8:
-		scan[0] = SDL_SCANCODE_F8;
-		return true;
-	case eAGSKeyCodeF9:
-		scan[0] = SDL_SCANCODE_F9;
-		return true;
-	case eAGSKeyCodeF10:
-		scan[0] = SDL_SCANCODE_F10;
-		return true;
-	case eAGSKeyCodeF11:
-		scan[0] = SDL_SCANCODE_F11;
-		return true;
-	case eAGSKeyCodeF12:
-		scan[0] = SDL_SCANCODE_F12;
-		return true;
-
-	case eAGSKeyCodeHome:
-		scan[0] = SDL_SCANCODE_KP_7;
-		scan[1] = SDL_SCANCODE_HOME;
-		return true;
-	case eAGSKeyCodeUpArrow:
-		scan[0] = SDL_SCANCODE_KP_8;
-		scan[1] = SDL_SCANCODE_UP;
-		return true;
-	case eAGSKeyCodePageUp:
-		scan[0] = SDL_SCANCODE_KP_9;
-		scan[1] = SDL_SCANCODE_PAGEUP;
-		return true;
-	case eAGSKeyCodeLeftArrow:
-		scan[0] = SDL_SCANCODE_KP_4;
-		scan[1] = SDL_SCANCODE_LEFT;
-		return true;
-	case eAGSKeyCodeNumPad5:
-		scan[0] = SDL_SCANCODE_KP_5;
-		return true;
-	case eAGSKeyCodeRightArrow:
-		scan[0] = SDL_SCANCODE_KP_6;
-		scan[1] = SDL_SCANCODE_RIGHT;
-		return true;
-	case eAGSKeyCodeEnd:
-		scan[0] = SDL_SCANCODE_KP_1;
-		scan[1] = SDL_SCANCODE_END;
-		return true;
-	case eAGSKeyCodeDownArrow:
-		scan[0] = SDL_SCANCODE_KP_2;
-		scan[1] = SDL_SCANCODE_DOWN;
-		return true;
-	case eAGSKeyCodePageDown:
-		scan[0] = SDL_SCANCODE_KP_3;
-		scan[1] = SDL_SCANCODE_PAGEDOWN;
-		return true;
-	case eAGSKeyCodeInsert:
-		scan[0] = SDL_SCANCODE_KP_0;
-		scan[1] = SDL_SCANCODE_INSERT;
-		return true;
-	case eAGSKeyCodeDelete:
-		scan[0] = SDL_SCANCODE_KP_PERIOD;
-		scan[1] = SDL_SCANCODE_DELETE;
-		return true;
-
-	case eAGSKeyCodeLShift:
-		scan[0] = SDL_SCANCODE_LSHIFT;
-		return true;
-	case eAGSKeyCodeRShift:
-		scan[0] = SDL_SCANCODE_RSHIFT;
-		return true;
-	case eAGSKeyCodeLCtrl:
-		scan[0] = SDL_SCANCODE_LCTRL;
-		return true;
-	case eAGSKeyCodeRCtrl:
-		scan[0] = SDL_SCANCODE_RCTRL;
-		return true;
-	case eAGSKeyCodeLAlt:
-		scan[0] = SDL_SCANCODE_LALT;
-		return true;
-	case eAGSKeyCodeRAlt:
-		scan[0] = SDL_SCANCODE_RALT;
-		return true;
-
-	default:
-		return false;
-	}
-#else
-	error("TODO: ags_key_to_sdl_scan");
-#endif
-	return false;
-}
-
-
 // ----------------------------------------------------------------------------
 // KEYBOARD INPUT
 // ----------------------------------------------------------------------------
 
-#ifdef TODO
-// Because our game engine still uses input polling, we have to accumulate
-// key events for our internal use whenever engine have to query key input.
-static Common::Queue<Common::Event> g_keyEvtQueue;
-#endif
-
 bool ags_keyevent_ready() {
-#ifdef TODO
-	return g_keyEvtQueue.size() > 0;
-#else
-	return false;
-#endif
+	return ::AGS::g_events->keypressed();
 }
 
-#ifdef TODO
-SDL_Event ags_get_next_keyevent() {
-	if (g_keyEvtQueue.size() > 0) {
-		auto evt = g_keyEvtQueue.front();
-		g_keyEvtQueue.pop_front();
-		return evt;
-	}
-	SDL_Event empty = {};
-	return empty;
+Common::Event ags_get_next_keyevent() {
+	return ::AGS::g_events->readKey();
 }
-#endif
 
 int ags_iskeydown(eAGSKeyCode ags_key) {
-#ifdef TODO
-	SDL_PumpEvents();
-	const Uint8 *state = SDL_GetKeyboardState(NULL);
-	SDL_Scancode scan[3];
-	if (!ags_key_to_sdl_scan(ags_key, scan))
-		return -1;
-	return (state[scan[0]] || state[scan[1]] || state[scan[2]]);
-#else
-	return 0;
-#endif
+	return ::AGS::g_events->isKeyPressed(ags_key);
 }
 
 void ags_simulate_keypress(eAGSKeyCode ags_key) {
-#ifdef TODO
-	SDL_Scancode scan[3];
-	if (!ags_key_to_sdl_scan(ags_key, scan))
+	Common::KeyCode keycode[3];
+	if (!::AGS::EventsManager::ags_key_to_scancode(ags_key, keycode))
 		return;
+
 	// Push a key event to the event queue; note that this won't affect the key states array
-	SDL_Event sdlevent = {};
-	sdl_G(event).type = SDL_KEYDOWN;
-	sdl_G(event).key.keysym.sym = SDL_GetKeyFromScancode(scan[0]);
-	sdl_G(event).key.keysym.scancode = scan[0];
-	SDL_PushEvent(&sdlevent);
-#endif
+	Common::Event e;
+	e.type = Common::EVENT_KEYDOWN;
+	e.kbd.keycode = keycode[0];
+	e.kbd.ascii = (e.kbd.keycode >= 32 && e.kbd.keycode <= 127) ? e.kbd.keycode : 0;
+
+	::AGS::g_events->pushKeyboardEvent(e);
 }
 
 #ifdef TODO
-static void on_sdl_key_down(const SDL_Event &event) {
+static void on_sdl_key_down(const Common::Event &event) {
 	// Engine is not structured very well yet, and we cannot pass this event where it's needed;
 	// instead we save it in the queue where it will be ready whenever any component asks for one.
 	g_keyEvtQueue.push_back(event);
@@ -394,7 +98,7 @@ static void on_sdl_key_down(const SDL_Event &event) {
 #endif
 
 #ifdef TODO
-static void on_sdl_textinput(const SDL_Event &event) {
+static void on_sdl_textinput(const Common::Event &event) {
 	// We also push text input events to the same queue, as this is only valid way to get proper
 	// text interpretation of the pressed key combination based on current system locale.
 	g_keyEvtQueue.push_back(event);
@@ -586,7 +290,7 @@ void sys_evt_set_focus_callbacks(void(*switch_in)(void), void(*switch_out)(void)
 }
 
 #ifdef TODO
-void sys_evt_process_one(const SDL_Event &event) {
+void sys_evt_process_one(const Common::Event &event) {
 	switch (_G(event).type) {
 	// GENERAL
 	case SDL_QUIT:
@@ -635,7 +339,7 @@ void sys_evt_process_one(const SDL_Event &event) {
 
 void sys_evt_process_pending(void) {
 #ifdef TODO
-	SDL_Event event;
+	Common::Event event;
 	while (SDL_PollEvent(&event)) {
 		sys_evt_process_one(event);
 	}
diff --git a/engines/ags/engine/ac/sys_events.h b/engines/ags/engine/ac/sys_events.h
index 93fe3558b3..4dcfe9639b 100644
--- a/engines/ags/engine/ac/sys_events.h
+++ b/engines/ags/engine/ac/sys_events.h
@@ -77,7 +77,7 @@ inline int make_merged_mod(int mod) {
 // Tells if there are any buffered key events
 bool ags_keyevent_ready();
 // Queries for the next key event in buffer; returns uninitialized data if none was queued
-SDL_Event ags_get_next_keyevent();
+Common::Event ags_get_next_keyevent();
 // Tells if the key is currently down, provided AGS key;
 // Returns positive value if it's down, 0 if it's not, negative value if the key code is not supported.
 // NOTE: for particular script codes this function returns positive if either of two keys are down.
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 662f6b0505..ba55c08df4 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -173,7 +173,6 @@ static void lock_mouse_on_click() {
 		_GP(mouse).TryLockToWindow();
 }
 
-#ifdef DEPRECATED
 static void toggle_mouse_lock() {
 	if (_GP(scsystem).windowed) {
 		if (_GP(mouse).IsLockedToWindow())
@@ -182,7 +181,6 @@ static void toggle_mouse_lock() {
 			_GP(mouse).TryLockToWindow();
 	}
 }
-#endif
 
 // Runs default mouse button handling
 static void check_mouse_controls() {
@@ -248,11 +246,11 @@ int old_key_mod = 0; // for saving previous key mods
 // Runs service key controls, returns false if service key combinations were handled
 // and no more processing required, otherwise returns true and provides current keycode and key shifts.
 bool run_service_key_controls(int &out_key) {
-#ifdef TODO
 	bool handled = false;
 	const bool key_valid = ags_keyevent_ready();
-	const SDL_Event key_evt = key_valid ? ags_get_next_keyevent() : SDL_Event();
-	const bool is_only_mod_key = key_evt.type == SDL_KEYDOWN ? is_mod_key(key_evt.key.keysym) : false;
+	const Common::Event key_evt = key_valid ? ags_get_next_keyevent() : Common::Event();
+	const bool is_only_mod_key = key_evt.type == Common::EVENT_KEYDOWN ?
+		is_mod_key(key_evt.kbd.keycode) : false;
 
 	// Following section is for testing for pushed and released mod-keys.
 	// A bit of explanation: some service actions may require combination of
@@ -270,7 +268,7 @@ bool run_service_key_controls(int &out_key) {
 	// TODO: maybe split this mod handling into sep procedure and make it easier to use (not that it's used alot)?
 
 	// First, check mods
-	const int cur_mod = make_merged_mod(SDL_GetModState());
+	const int cur_mod = make_merged_mod(key_evt.kbd.flags);
 
 	// If shifts combination have already triggered an action, then do nothing
 	// until new shifts are empty, in which case reset saved shifts
@@ -292,7 +290,7 @@ bool run_service_key_controls(int &out_key) {
 		// and set KEY_MODS_FIRED flag to prevent multiple execution
 		else if (old_key_mod) {
 			// Toggle mouse lock on Ctrl + Alt
-			if (old_key_mod == (KMOD_CTRL | KMOD_ALT)) {
+			if (old_key_mod == (Common::KBD_CTRL | Common::KBD_ALT)) {
 				toggle_mouse_lock();
 				handled = true;
 			}
@@ -307,12 +305,12 @@ bool run_service_key_controls(int &out_key) {
 		return false; // rest of engine currently does not use pressed mod keys
 	// change this when it's no longer true (but be mindful about key-skipping!)
 
-	int agskey = ags_keycode_from_sdl(key_evt);
+	int agskey = ::AGS::EventsManager::ags_keycode_from_scummvm(key_evt);
 	if (agskey == eAGSKeyCodeNone)
 		return false; // should skip this key event
 
 	// LAlt or RAlt + Enter/Return
-	if ((cur_mod == KMOD_ALT) && agskey == eAGSKeyCodeReturn) {
+	if ((cur_mod == Common::KBD_ALT) && agskey == eAGSKeyCodeReturn) {
 		engine_try_switch_windowed_gfxmode();
 		return false;
 	}
@@ -381,7 +379,7 @@ bool run_service_key_controls(int &out_key) {
 		return false;
 	}
 
-	if (((agskey == eAGSKeyCodeCtrlV) && (cur_key_mods & KMOD_ALT) != 0)
+	if (((agskey == eAGSKeyCodeCtrlV) && (cur_key_mods & Common::KBD_ALT) != 0)
 	        && (_GP(play).wait_counter < 1) && (_G(is_text_overlay) == 0) && (_G(restrict_until) == 0)) {
 		// make sure we can't interrupt a Wait()
 		// and desync the music to cutscene
@@ -393,7 +391,6 @@ bool run_service_key_controls(int &out_key) {
 
 	// No service operation triggered? return active keypress and mods to caller
 	out_key = agskey;
-#endif
 	return true;
 }
 
diff --git a/engines/ags/events.cpp b/engines/ags/events.cpp
index d49f8b0ccb..6ca141df24 100644
--- a/engines/ags/events.cpp
+++ b/engines/ags/events.cpp
@@ -67,16 +67,13 @@ void EventsManager::pollEvents() {
 			break;
 
 		case Common::EVENT_KEYDOWN:
-			updateKeys(e.kbd, true);
-
-			if (!isModifierKey(e.kbd.keycode)) {
-				// Add keypresses to the pending key list
-				_pendingKeys.push(e.kbd);
-			}
+			updateKeys(e, true);
+			_pendingKeys.push(e);
 			break;
 
 		case Common::EVENT_KEYUP:
-			updateKeys(e.kbd, false);
+			updateKeys(e, false);
+			_pendingKeys.push(e);
 			break;
 
 		default:
@@ -103,24 +100,9 @@ bool EventsManager::keypressed() {
 
 #define EXTENDED_KEY_CODE ('\0')
 
-int EventsManager::readKey() {
+Common::Event EventsManager::readKey() {
 	pollEvents();
-	if (_pendingKeys.empty())
-		return 0;
-
-	Common::KeyState keyState = _pendingKeys.pop();
-
-	int scancode = getScancode(keyState.keycode);
-	int code = scancode << 8;
-
-	if (isExtendedKey(keyState.keycode))
-		code |= EXTENDED_KEY_CODE;
-	else if ((keyState.flags & (Common::KBD_CTRL | Common::KBD_ALT)) == 0)
-		code |= keyState.ascii;
-	else
-		code |= scancode;
-
-	return code;
+	return _pendingKeys.empty() ? Common::Event() : _pendingKeys.pop();
 }
 
 Common::Event EventsManager::readEvent() {
@@ -168,121 +150,19 @@ bool EventsManager::isExtendedKey(const Common::KeyCode &keycode) const {
 	return false;
 }
 
-int EventsManager::getScancode(Common::KeyCode keycode) const {
-	if (keycode >= Common::KEYCODE_a && keycode <= Common::KEYCODE_z)
-		return (int)keycode - Common::KEYCODE_a + AGS3::__allegro_KEY_A;
-	if (keycode >= Common::KEYCODE_0 && keycode <= Common::KEYCODE_9)
-		return (int)keycode - Common::KEYCODE_0 + AGS3::__allegro_KEY_0;
-	if (keycode >= Common::KEYCODE_KP0 && keycode <= Common::KEYCODE_KP9)
-		return (int)keycode - Common::KEYCODE_KP0 + AGS3::__allegro_KEY_0_PAD;
-	if (keycode >= Common::KEYCODE_F1 && keycode <= Common::KEYCODE_F12)
-		return (int)keycode - Common::KEYCODE_F1 + AGS3::__allegro_KEY_F1;
-
-	switch (keycode) {
-	case Common::KEYCODE_ESCAPE:
-		return AGS3::__allegro_KEY_ESC;
-	case Common::KEYCODE_TILDE:
-		return AGS3::__allegro_KEY_TILDE;
-	case Common::KEYCODE_MINUS:
-		return AGS3::__allegro_KEY_MINUS;
-	case Common::KEYCODE_EQUALS:
-		return AGS3::__allegro_KEY_EQUALS;
-	case Common::KEYCODE_BACKSPACE:
-		return AGS3::__allegro_KEY_BACKSPACE;
-	case Common::KEYCODE_TAB:
-		return AGS3::__allegro_KEY_TAB;
-	case Common::KEYCODE_LEFTBRACKET:
-		return AGS3::__allegro_KEY_OPENBRACE;
-	case Common::KEYCODE_RIGHTBRACKET:
-		return AGS3::__allegro_KEY_CLOSEBRACE;
-	case Common::KEYCODE_RETURN:
-		return AGS3::__allegro_KEY_ENTER;
-	case Common::KEYCODE_COLON:
-		return AGS3::__allegro_KEY_COLON;
-	case Common::KEYCODE_QUOTE:
-		return AGS3::__allegro_KEY_QUOTE;
-	case Common::KEYCODE_BACKSLASH:
-		return AGS3::__allegro_KEY_BACKSLASH;
-	case Common::KEYCODE_COMMA:
-		return AGS3::__allegro_KEY_COMMA;
-	case Common::KEYCODE_SLASH:
-		return AGS3::__allegro_KEY_SLASH;
-	case Common::KEYCODE_SPACE:
-		return AGS3::__allegro_KEY_SPACE;
-	case Common::KEYCODE_INSERT:
-		return AGS3::__allegro_KEY_INSERT;
-	case Common::KEYCODE_DELETE:
-		return AGS3::__allegro_KEY_DEL;
-	case Common::KEYCODE_HOME:
-		return AGS3::__allegro_KEY_HOME;
-	case Common::KEYCODE_END:
-		return AGS3::__allegro_KEY_END;
-	case Common::KEYCODE_PAGEUP:
-		return AGS3::__allegro_KEY_PGUP;
-	case Common::KEYCODE_PAGEDOWN:
-		return AGS3::__allegro_KEY_PGDN;
-	case Common::KEYCODE_LEFT:
-		return AGS3::__allegro_KEY_LEFT;
-	case Common::KEYCODE_RIGHT:
-		return AGS3::__allegro_KEY_RIGHT;
-	case Common::KEYCODE_UP:
-		return AGS3::__allegro_KEY_UP;
-	case Common::KEYCODE_DOWN:
-		return AGS3::__allegro_KEY_DOWN;
-	case Common::KEYCODE_KP_DIVIDE:
-		return AGS3::__allegro_KEY_SLASH_PAD;
-	case Common::KEYCODE_ASTERISK:
-		return AGS3::__allegro_KEY_ASTERISK;
-	case Common::KEYCODE_KP_MINUS:
-		return AGS3::__allegro_KEY_MINUS_PAD;
-	case Common::KEYCODE_KP_PLUS:
-		return AGS3::__allegro_KEY_PLUS_PAD;
-	case Common::KEYCODE_KP_PERIOD:
-		return AGS3::__allegro_KEY_DEL_PAD;
-	case Common::KEYCODE_KP_ENTER:
-		return AGS3::__allegro_KEY_ENTER_PAD;
-	case Common::KEYCODE_PRINT:
-		return AGS3::__allegro_KEY_PRTSCR;
-	case Common::KEYCODE_PAUSE:
-		return AGS3::__allegro_KEY_PAUSE;
-	case Common::KEYCODE_SEMICOLON:
-		return AGS3::__allegro_KEY_SEMICOLON;
-
-	case Common::KEYCODE_LSHIFT:
-		return AGS3::__allegro_KEY_LSHIFT;
-	case Common::KEYCODE_RSHIFT:
-		return AGS3::__allegro_KEY_RSHIFT;
-	case Common::KEYCODE_LCTRL:
-		return AGS3::__allegro_KEY_LCONTROL;
-	case Common::KEYCODE_RCTRL:
-		return AGS3::__allegro_KEY_RCONTROL;
-	case Common::KEYCODE_LALT:
-		return AGS3::__allegro_KEY_ALT;
-	case Common::KEYCODE_RALT:
-		return AGS3::__allegro_KEY_ALT;
-	case Common::KEYCODE_SCROLLOCK:
-		return AGS3::__allegro_KEY_SCRLOCK;
-	case Common::KEYCODE_NUMLOCK:
-		return AGS3::__allegro_KEY_NUMLOCK;
-	case Common::KEYCODE_CAPSLOCK:
-		return AGS3::__allegro_KEY_CAPSLOCK;
-	default:
-		return 0;
-	}
-}
-
-void EventsManager::updateKeys(const Common::KeyState &keyState, bool isDown) {
+void EventsManager::updateKeys(const Common::Event &event, bool isDown) {
 	// Update the keys array with whether the key is pressed
-	int scancode = getScancode(keyState.keycode);
-	if (scancode != 0)
-		_keys[scancode] = isDown;
+	
+	AGS3::eAGSKeyCode key = ags_keycode_from_scummvm(event);
+	if (key != 0)
+		_keys[key] = isDown;
 }
 
 uint EventsManager::getModifierFlags() const {
 	if (_pendingKeys.empty())
 		return 0;
 
-	byte flags = _pendingKeys.front().flags;
+	byte flags = _pendingKeys.front().kbd.flags;
 	uint keyFlags = 0;
 	if (flags & Common::KBD_SHIFT)
 		keyFlags |= AGS3::__allegro_KB_SHIFT_FLAG;
@@ -302,8 +182,248 @@ uint EventsManager::getModifierFlags() const {
 	return keyFlags;
 }
 
-bool EventsManager::isKeyPressed(AGS3::AllegroKbdKeycode keycode) const {
-	return _keys[keycode];
+bool EventsManager::isKeyPressed(AGS3::eAGSKeyCode key) {
+	pollEvents();
+	return _keys[key];
+}
+
+bool EventsManager::ags_key_to_scancode(AGS3::eAGSKeyCode key, Common::KeyCode(&kc)[3]) {
+	kc[0] = Common::KEYCODE_INVALID;
+	kc[1] = Common::KEYCODE_INVALID;
+	kc[2] = Common::KEYCODE_INVALID;
+	Common::KeyCode sym = Common::KEYCODE_INVALID;
+
+	// SDL sym codes happen to match small ASCII letters, so lowercase ours if necessary
+	if (key >= AGS3::eAGSKeyCodeA && key <= AGS3::eAGSKeyCodeZ) {
+		sym = static_cast<Common::KeyCode>(key - AGS3::eAGSKeyCodeA + Common::KEYCODE_a);
+	}
+	// Rest of the printable characters seem to match (and match ascii codes)
+	else if (key >= AGS3::eAGSKeyCodeSpace && key <= AGS3::eAGSKeyCodeBackquote) {
+		sym = static_cast<Common::KeyCode>(key);
+	}
+
+	if (sym != Common::KEYCODE_INVALID) {
+		kc[0] = sym;
+		return true;
+	}
+
+	// Other keys are mapped directly to scancode (based on [sonneveld]'s code)
+	switch (key) {
+	case AGS3::eAGSKeyCodeBackspace:
+		kc[0] = Common::KEYCODE_BACKSPACE;
+		return true;
+	case AGS3::eAGSKeyCodeTab:
+		kc[0] = Common::KEYCODE_TAB;
+		return true;
+	case AGS3::eAGSKeyCodeReturn:
+		kc[0] = Common::KEYCODE_RETURN;
+		kc[1] = Common::KEYCODE_KP_ENTER;
+		return true;
+	case AGS3::eAGSKeyCodeEscape:
+		kc[0] = Common::KEYCODE_ESCAPE;
+		return true;
+
+	case AGS3::eAGSKeyCodeF1:
+		kc[0] = Common::KEYCODE_F1;
+		return true;
+	case AGS3::eAGSKeyCodeF2:
+		kc[0] = Common::KEYCODE_F2;
+		return true;
+	case AGS3::eAGSKeyCodeF3:
+		kc[0] = Common::KEYCODE_F3;
+		return true;
+	case AGS3::eAGSKeyCodeF4:
+		kc[0] = Common::KEYCODE_F4;
+		return true;
+	case AGS3::eAGSKeyCodeF5:
+		kc[0] = Common::KEYCODE_F5;
+		return true;
+	case AGS3::eAGSKeyCodeF6:
+		kc[0] = Common::KEYCODE_F6;
+		return true;
+	case AGS3::eAGSKeyCodeF7:
+		kc[0] = Common::KEYCODE_F7;
+		return true;
+	case AGS3::eAGSKeyCodeF8:
+		kc[0] = Common::KEYCODE_F8;
+		return true;
+	case AGS3::eAGSKeyCodeF9:
+		kc[0] = Common::KEYCODE_F9;
+		return true;
+	case AGS3::eAGSKeyCodeF10:
+		kc[0] = Common::KEYCODE_F10;
+		return true;
+	case AGS3::eAGSKeyCodeF11:
+		kc[0] = Common::KEYCODE_F11;
+		return true;
+	case AGS3::eAGSKeyCodeF12:
+		kc[0] = Common::KEYCODE_F12;
+		return true;
+
+	case AGS3::eAGSKeyCodeHome:
+		kc[0] = Common::KEYCODE_KP7;
+		kc[1] = Common::KEYCODE_HOME;
+		return true;
+	case AGS3::eAGSKeyCodeUpArrow:
+		kc[0] = Common::KEYCODE_KP8;
+		kc[1] = Common::KEYCODE_UP;
+		return true;
+	case AGS3::eAGSKeyCodePageUp:
+		kc[0] = Common::KEYCODE_KP9;
+		kc[1] = Common::KEYCODE_PAGEUP;
+		return true;
+	case AGS3::eAGSKeyCodeLeftArrow:
+		kc[0] = Common::KEYCODE_KP4;
+		kc[1] = Common::KEYCODE_LEFT;
+		return true;
+	case AGS3::eAGSKeyCodeNumPad5:
+		kc[0] = Common::KEYCODE_KP5;
+		return true;
+	case AGS3::eAGSKeyCodeRightArrow:
+		kc[0] = Common::KEYCODE_KP6;
+		kc[1] = Common::KEYCODE_RIGHT;
+		return true;
+	case AGS3::eAGSKeyCodeEnd:
+		kc[0] = Common::KEYCODE_KP1;
+		kc[1] = Common::KEYCODE_END;
+		return true;
+	case AGS3::eAGSKeyCodeDownArrow:
+		kc[0] = Common::KEYCODE_KP2;
+		kc[1] = Common::KEYCODE_DOWN;
+		return true;
+	case AGS3::eAGSKeyCodePageDown:
+		kc[0] = Common::KEYCODE_KP3;
+		kc[1] = Common::KEYCODE_PAGEDOWN;
+		return true;
+	case AGS3::eAGSKeyCodeInsert:
+		kc[0] = Common::KEYCODE_KP0;
+		kc[1] = Common::KEYCODE_INSERT;
+		return true;
+	case AGS3::eAGSKeyCodeDelete:
+		kc[0] = Common::KEYCODE_KP_PERIOD;
+		kc[1] = Common::KEYCODE_DELETE;
+		return true;
+
+	case AGS3::eAGSKeyCodeLShift:
+		kc[0] = Common::KEYCODE_LSHIFT;
+		return true;
+	case AGS3::eAGSKeyCodeRShift:
+		kc[0] = Common::KEYCODE_RSHIFT;
+		return true;
+	case AGS3::eAGSKeyCodeLCtrl:
+		kc[0] = Common::KEYCODE_LCTRL;
+		return true;
+	case AGS3::eAGSKeyCodeRCtrl:
+		kc[0] = Common::KEYCODE_RCTRL;
+		return true;
+	case AGS3::eAGSKeyCodeLAlt:
+		kc[0] = Common::KEYCODE_LALT;
+		return true;
+	case AGS3::eAGSKeyCodeRAlt:
+		kc[0] = Common::KEYCODE_RALT;
+		return true;
+
+	default:
+		return false;
+	}
+	return false;
+}
+
+AGS3::eAGSKeyCode EventsManager::ags_keycode_from_scummvm(const Common::Event &event) {
+	if (event.type != Common::EVENT_KEYDOWN)
+		return AGS3::eAGSKeyCodeNone;
+
+	if (event.kbd.ascii >= 32 && event.kbd.ascii <= 127)
+		return static_cast<AGS3::eAGSKeyCode>(event.kbd.ascii);
+
+	const Common::KeyCode sym = event.kbd.keycode;
+	const uint16 mod = event.kbd.flags;
+
+	// Ctrl and Alt combinations realign the letter code to certain offset
+	if (sym >= Common::KEYCODE_a && sym <= Common::KEYCODE_z) {
+		if ((mod & Common::KBD_CTRL) != 0) // align letters to code 1
+			return static_cast<AGS3::eAGSKeyCode>(0 + (sym - Common::KEYCODE_a) + 1);
+		else if ((mod & Common::KBD_ALT) != 0) // align letters to code 301
+			return static_cast<AGS3::eAGSKeyCode>(AGS_EXT_KEY_SHIFT + (sym - Common::KEYCODE_a) + 1);
+	}
+
+	// Remaining codes may match or not, but we use a big table anyway.
+	// TODO: this is code by [sonneveld],
+	// double check that we must use scan codes here, maybe can use sdl key (sym) too?
+	switch (sym) {
+	case Common::KEYCODE_BACKSPACE:
+		return AGS3::eAGSKeyCodeBackspace;
+	case Common::KEYCODE_TAB:
+		return AGS3::eAGSKeyCodeTab;
+	case Common::KEYCODE_RETURN:
+	case Common::KEYCODE_KP_ENTER:
+		return AGS3::eAGSKeyCodeReturn;
+	case Common::KEYCODE_ESCAPE:
+		return AGS3::eAGSKeyCodeEscape;
+
+	case Common::KEYCODE_F1:
+		return AGS3::eAGSKeyCodeF1;
+	case Common::KEYCODE_F2:
+		return AGS3::eAGSKeyCodeF2;
+	case Common::KEYCODE_F3:
+		return AGS3::eAGSKeyCodeF3;
+	case Common::KEYCODE_F4:
+		return AGS3::eAGSKeyCodeF4;
+	case Common::KEYCODE_F5:
+		return AGS3::eAGSKeyCodeF5;
+	case Common::KEYCODE_F6:
+		return AGS3::eAGSKeyCodeF6;
+	case Common::KEYCODE_F7:
+		return AGS3::eAGSKeyCodeF7;
+	case Common::KEYCODE_F8:
+		return AGS3::eAGSKeyCodeF8;
+	case Common::KEYCODE_F9:
+		return AGS3::eAGSKeyCodeF9;
+	case Common::KEYCODE_F10:
+		return AGS3::eAGSKeyCodeF10;
+	case Common::KEYCODE_F11:
+		return AGS3::eAGSKeyCodeF11;
+	case Common::KEYCODE_F12:
+		return AGS3::eAGSKeyCodeF12;
+
+	case Common::KEYCODE_KP7:
+	case Common::KEYCODE_HOME:
+		return AGS3::eAGSKeyCodeHome;
+	case Common::KEYCODE_KP8:
+	case Common::KEYCODE_UP:
+		return AGS3::eAGSKeyCodeUpArrow;
+	case Common::KEYCODE_KP9:
+	case Common::KEYCODE_PAGEUP:
+		return AGS3::eAGSKeyCodePageUp;
+	case Common::KEYCODE_KP4:
+	case Common::KEYCODE_LEFT:
+		return AGS3::eAGSKeyCodeLeftArrow;
+	case Common::KEYCODE_KP5:
+		return AGS3::eAGSKeyCodeNumPad5;
+	case Common::KEYCODE_KP6:
+	case Common::KEYCODE_RIGHT:
+		return AGS3::eAGSKeyCodeRightArrow;
+	case Common::KEYCODE_KP1:
+	case Common::KEYCODE_END:
+		return AGS3::eAGSKeyCodeEnd;
+	case Common::KEYCODE_KP2:
+	case Common::KEYCODE_DOWN:
+		return AGS3::eAGSKeyCodeDownArrow;
+	case Common::KEYCODE_KP3:
+	case Common::KEYCODE_PAGEDOWN:
+		return AGS3::eAGSKeyCodePageDown;
+	case Common::KEYCODE_KP0:
+	case Common::KEYCODE_INSERT:
+		return AGS3::eAGSKeyCodeInsert;
+	case Common::KEYCODE_KP_PERIOD:
+	case Common::KEYCODE_DELETE:
+		return AGS3::eAGSKeyCodeDelete;
+
+	default:
+		return AGS3::eAGSKeyCodeNone;
+	}
+
+	return AGS3::eAGSKeyCodeNone;
 }
 
 } // namespace AGS
diff --git a/engines/ags/events.h b/engines/ags/events.h
index 5b45fbdeda..3fdaae4d3e 100644
--- a/engines/ags/events.h
+++ b/engines/ags/events.h
@@ -24,6 +24,7 @@
 #define AGS_EVENTS_H
 
 #include "lib/allegro/keyboard.h"
+#include "shared/ac/keycode.h"
 #include "common/array.h"
 #include "common/queue.h"
 #include "common/events.h"
@@ -33,7 +34,7 @@ namespace AGS {
 class EventsManager {
 private:
 	Common::Queue<Common::Event> _pendingEvents;
-	Common::Queue<Common::KeyState> _pendingKeys;
+	Common::Queue<Common::Event> _pendingKeys;
 	Common::Array<bool> _keys;
 	Common::Point _mousePos;
 	int16 _joystickAxis[32];
@@ -41,9 +42,19 @@ private:
 
 	bool isModifierKey(const Common::KeyCode &keycode) const;
 	bool isExtendedKey(const Common::KeyCode &keycode) const;
-	int getScancode(Common::KeyCode keycode) const;
 
-	void updateKeys(const Common::KeyState &keyState, bool isDown);
+	void updateKeys(const Common::Event &event, bool isDown);
+public:
+	/**
+	 * Converts ags key to ScummVM scancode
+	 */
+	static bool ags_key_to_scancode(AGS3::eAGSKeyCode key, Common::KeyCode(&kc)[3]);
+
+	/*
+	 * Converts a ScummVM event to the ags keycode
+	 */
+	static AGS3::eAGSKeyCode ags_keycode_from_scummvm(const Common::Event &event);
+
 public:
 	EventsManager();
 	~EventsManager();
@@ -59,9 +70,17 @@ public:
 	bool keypressed();
 
 	/**
-	 * Returns the next keypress, if any is pending
+	 * Returns the next keyboard event, if any is pending
 	 */
-	int readKey();
+	Common::Event readKey();
+
+	/**
+	 * Pushes a keydown event into the keypresses queue,
+	 * without updating the key down flag array
+	 */
+	void pushKeyboardEvent(const Common::Event &evt) {
+		_pendingKeys.push(evt);
+	}
 
 	/**
 	 * Returns the next event, if any
@@ -76,7 +95,7 @@ public:
 	/**
 	 * Returns true if a given key is pressed
 	 */
-	bool isKeyPressed(AGS3::AllegroKbdKeycode keycode) const;
+	bool isKeyPressed(AGS3::eAGSKeyCode key);
 
 	/**
 	 * Returns the bitset of currently pressed modifier keys
diff --git a/engines/ags/lib/allegro/keyboard.cpp b/engines/ags/lib/allegro/keyboard.cpp
index 0ff4edc2b7..3783282070 100644
--- a/engines/ags/lib/allegro/keyboard.cpp
+++ b/engines/ags/lib/allegro/keyboard.cpp
@@ -68,8 +68,4 @@ bool keypressed() {
 	return ::AGS::g_events->keypressed();
 }
 
-int readkey() {
-	return ::AGS::g_events->readKey();
-}
-
 } // namespace AGS3
diff --git a/engines/ags/lib/allegro/keyboard.h b/engines/ags/lib/allegro/keyboard.h
index e1f3dc8b55..7e75517aee 100644
--- a/engines/ags/lib/allegro/keyboard.h
+++ b/engines/ags/lib/allegro/keyboard.h
@@ -337,7 +337,6 @@ AL_FUNC(void, simulate_keypress, (int keycode));
 AL_FUNC(void, simulate_ukeypress, (int keycode, int scancode));
 
 AL_FUNC(bool, keypressed, (void));
-AL_FUNC(int, readkey, (void));
 
 } // namespace AGS3
 


Commit: 5f4b6d74e3bbd26ba18240570365afe0e768e7c6
    https://github.com/scummvm/scummvm/commit/5f4b6d74e3bbd26ba18240570365afe0e768e7c6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:51-07:00

Commit Message:
AGS: Re-add proper class initializations

Changed paths:
    engines/ags/engine/ac/dynobj/script_audio_channel.h
    engines/ags/engine/ac/dynobj/script_hotspot.h
    engines/ags/engine/ac/dynobj/script_inv_item.h
    engines/ags/engine/ac/dynobj/script_object.h
    engines/ags/engine/ac/dynobj/script_region.h
    engines/ags/engine/ac/game_state.cpp
    engines/ags/engine/ac/game_state.h
    engines/ags/engine/ac/object_cache.h
    engines/ags/engine/ac/room_status.h
    engines/ags/engine/gui/animating_gui_button.h
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/shared/ac/game_struct_defines.h


diff --git a/engines/ags/engine/ac/dynobj/script_audio_channel.h b/engines/ags/engine/ac/dynobj/script_audio_channel.h
index b3cc119cb0..2c185cc762 100644
--- a/engines/ags/engine/ac/dynobj/script_audio_channel.h
+++ b/engines/ags/engine/ac/dynobj/script_audio_channel.h
@@ -26,8 +26,8 @@
 namespace AGS3 {
 
 struct ScriptAudioChannel {
-	int id;
-	int reserved;
+	int id = 0;
+	int reserved = 0;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/script_hotspot.h b/engines/ags/engine/ac/dynobj/script_hotspot.h
index e7f7074e89..239871b06d 100644
--- a/engines/ags/engine/ac/dynobj/script_hotspot.h
+++ b/engines/ags/engine/ac/dynobj/script_hotspot.h
@@ -26,8 +26,8 @@
 namespace AGS3 {
 
 struct ScriptHotspot {
-	int id;
-	int reserved;
+	int id = 0;
+	int reserved = 0;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/script_inv_item.h b/engines/ags/engine/ac/dynobj/script_inv_item.h
index 7bb3a1243d..5f817eda44 100644
--- a/engines/ags/engine/ac/dynobj/script_inv_item.h
+++ b/engines/ags/engine/ac/dynobj/script_inv_item.h
@@ -26,8 +26,8 @@
 namespace AGS3 {
 
 struct ScriptInvItem {
-	int id;
-	int reserved;
+	int id = 0;
+	int reserved = 0;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/script_object.h b/engines/ags/engine/ac/dynobj/script_object.h
index 09169551f5..db83493e60 100644
--- a/engines/ags/engine/ac/dynobj/script_object.h
+++ b/engines/ags/engine/ac/dynobj/script_object.h
@@ -29,9 +29,9 @@ namespace AGS3 {
 
 // 64 bit: Struct size must be 8 byte for scripts to work
 struct ScriptObject {
-	int id;
+	int id = 0;
 	//RoomObject *obj;
-	int __padding;
+	int __padding = 0;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/dynobj/script_region.h b/engines/ags/engine/ac/dynobj/script_region.h
index bcb45c5572..95abbc8c29 100644
--- a/engines/ags/engine/ac/dynobj/script_region.h
+++ b/engines/ags/engine/ac/dynobj/script_region.h
@@ -26,8 +26,8 @@
 namespace AGS3 {
 
 struct ScriptRegion {
-	int id;
-	int reserved;
+	int id = 0;
+	int reserved = 0;
 };
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/game_state.cpp b/engines/ags/engine/ac/game_state.cpp
index b6f49fa851..32d71ec41a 100644
--- a/engines/ags/engine/ac/game_state.cpp
+++ b/engines/ags/engine/ac/game_state.cpp
@@ -46,6 +46,23 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 GameState::GameState() {
+	Common::fill(&globalvars[0], &globalvars[MAXGLOBALVARS], 0);
+	Common::fill(&reserved[0], &reserved[GAME_STATE_RESERVED_INTS], 0);
+	Common::fill(&globalscriptvars[0], &globalscriptvars[MAXGSVALUES], 0);
+	Common::fill(&walkable_areas_on[0], &walkable_areas_on[MAX_WALK_AREAS + 1], 0);
+	Common::fill(&script_timers[0], &script_timers[MAX_TIMERS], 0);
+	Common::fill(&parsed_words[0], &parsed_words[MAX_PARSED_WORDS], 0);
+	Common::fill(&bad_parsed_word[0], &bad_parsed_word[100], 0);
+	Common::fill(&raw_modified[0], &raw_modified[MAX_ROOM_BGFRAMES], 0);
+	Common::fill(&filenumbers[0], &filenumbers[MAXSAVEGAMES], 0);
+	Common::fill(&music_queue[0], &music_queue[MAX_QUEUED_MUSIC], 0);
+	Common::fill(&takeover_from[0], &takeover_from[50], 0);
+	Common::fill(&playmp3file_name[0], &playmp3file_name[PLAYMP3FILE_MAX_FILENAME_LEN], 0);
+	Common::fill(&globalstrings[0][0], &globalstrings[MAXGLOBALSTRINGS][0], 0);
+	Common::fill(&lastParserEntry[0], &lastParserEntry[MAX_MAXSTRLEN], 0);
+	Common::fill(&game_name[0], &game_name[100], 0);
+	Common::fill(&default_audio_type_volumes[0], &default_audio_type_volumes[MAX_AUDIO_TYPES], 0);
+
 	_isAutoRoomViewport = true;
 	_mainViewportHasChanged = false;
 }
diff --git a/engines/ags/engine/ac/game_state.h b/engines/ags/engine/ac/game_state.h
index 9be2028fe7..d1abf2c6e1 100644
--- a/engines/ags/engine/ac/game_state.h
+++ b/engines/ags/engine/ac/game_state.h
@@ -69,162 +69,163 @@ enum GameStateSvgVersion {
 
 // Adding to this might need to modify AGSDEFNS.SH and AGSPLUGIN.H
 struct GameState {
-	int  score;      // player's current score
-	int  usedmode;   // set by ProcessClick to last cursor mode used
-	int  disabled_user_interface;  // >0 while in cutscene/etc
-	int  gscript_timer;    // obsolete
-	int  debug_mode;       // whether we're in debug mode
+	int  score = 0;      // player's current score
+	int  usedmode = 0;   // set by ProcessClick to last cursor mode used
+	int  disabled_user_interface = 0;  // >0 while in cutscene/etc
+	int  gscript_timer = 0;    // obsolete
+	int  debug_mode = 0;       // whether we're in debug mode
 	int  globalvars[MAXGLOBALVARS];  // obsolete
-	int  messagetime;      // time left for auto-remove messages
-	int  usedinv;          // inventory item last used
-	int  inv_top, inv_numdisp, obsolete_inv_numorder, inv_numinline;
-	int  text_speed;       // how quickly text is removed
-	int  sierra_inv_color; // background used to paint defualt inv window
-	int  talkanim_speed;   // animation speed of talking anims
-	int  inv_item_wid, inv_item_hit;  // set by SetInvDimensions
-	int  speech_text_shadow;         // colour of outline fonts (default black)
-	int  swap_portrait_side;         // sierra-style speech swap sides
-	int  speech_textwindow_gui;      // textwindow used for sierra-style speech
-	int  follow_change_room_timer;   // delay before moving following characters into new room
-	int  totalscore;           // maximum possible score
-	int  skip_display;         // how the user can skip normal Display windows
-	int  no_multiloop_repeat;  // for backwards compatibility
-	int  roomscript_finished;  // on_call finished in room
-	int  used_inv_on;          // inv item they clicked on
-	int  no_textbg_when_voice; // no textwindow bgrnd when voice speech is used
-	int  max_dialogoption_width; // max width of dialog options text window
-	int  no_hicolor_fadein;      // fade out but instant in for hi-color
-	int  bgspeech_game_speed;    // is background speech relative to game speed
-	int  bgspeech_stay_on_display; // whether to remove bg speech when DisplaySpeech is used
-	int  unfactor_speech_from_textlength; // remove "&10" when calculating time for text to stay
-	int  mp3_loop_before_end;    // (UNUSED!) loop this time before end of track (ms)
-	int  speech_music_drop;      // how much to drop music volume by when speech is played
-	int  in_cutscene;            // we are between a StartCutscene and EndCutscene
-	int  fast_forward;           // player has elected to skip cutscene
-	int  room_width;      // width of current room
-	int  room_height;     // height of current room
+	int  messagetime = 0;      // time left for auto-remove messages
+	int  usedinv = 0;          // inventory item last used
+	int  inv_top = 0, inv_numdisp = 0, obsolete_inv_numorder = 0, inv_numinline = 0;
+	int  text_speed = 0;       // how quickly text is removed
+	int  sierra_inv_color = 0; // background used to paint defualt inv window
+	int  talkanim_speed = 0;   // animation speed of talking anims
+	int  inv_item_wid = 0, inv_item_hit = 0;  // set by SetInvDimensions
+	int  speech_text_shadow = 0;         // colour of outline fonts (default black)
+	int  swap_portrait_side = 0;         // sierra-style speech swap sides
+	int  speech_textwindow_gui = 0;      // textwindow used for sierra-style speech
+	int  follow_change_room_timer = 0;   // delay before moving following characters into new room
+	int  totalscore = 0;           // maximum possible score
+	int  skip_display = 0;         // how the user can skip normal Display windows
+	int  no_multiloop_repeat = 0;  // for backwards compatibility
+	int  roomscript_finished = 0;  // on_call finished in room
+	int  used_inv_on = 0;          // inv item they clicked on
+	int  no_textbg_when_voice = 0; // no textwindow bgrnd when voice speech is used
+	int  max_dialogoption_width = 0; // max width of dialog options text window
+	int  no_hicolor_fadein = 0;      // fade out but instant in for hi-color
+	int  bgspeech_game_speed = 0;    // is background speech relative to game speed
+	int  bgspeech_stay_on_display = 0; // whether to remove bg speech when DisplaySpeech is used
+	int  unfactor_speech_from_textlength = 0; // remove "&10" when calculating time for text to stay
+	int  mp3_loop_before_end = 0;    // (UNUSED!) loop this time before end of track (ms)
+	int  speech_music_drop = 0;      // how much to drop music volume by when speech is played
+	int  in_cutscene = 0;            // we are between a StartCutscene and EndCutscene
+	int  fast_forward = 0;           // player has elected to skip cutscene
+	int  room_width = 0;      // width of current room
+	int  room_height = 0;     // height of current room
 	// ** up to here is referenced in the plugin interface
-	int  game_speed_modifier;
-	int  score_sound;
-	int  takeover_data;  // value passed to RunAGSGame in previous game
-	int  replay_hotkey_unused;  // (UNUSED!) StartRecording: not supported
-	int  dialog_options_x;
-	int  dialog_options_y;
-	int  narrator_speech;
-	int  ambient_sounds_persist;
-	int  lipsync_speed;
-	int  close_mouth_speech_time; // stop speech animation at (messagetime - close_mouth_speech_time)
+	int  game_speed_modifier = 0;
+	int  score_sound = 0;
+	int  takeover_data = 0;  // value passed to RunAGSGame in previous game
+	int  replay_hotkey_unused = 0;  // (UNUSED!) StartRecording: not supported
+	int  dialog_options_x = 0;
+	int  dialog_options_y = 0;
+	int  narrator_speech = 0;
+	int  ambient_sounds_persist = 0;
+	int  lipsync_speed = 0;
+	int  close_mouth_speech_time = 0; // stop speech animation at (messagetime - close_mouth_speech_time)
 	// (this is designed to work in text-only mode)
-	int  disable_antialiasing;
-	int  text_speed_modifier;
-	HorAlignment text_align;
-	int  speech_bubble_width;
-	int  min_dialogoption_width;
-	int  disable_dialog_parser;
-	int  anim_background_speed;  // the setting for this room
-	int  top_bar_backcolor;
-	int  top_bar_textcolor;
-	int  top_bar_bordercolor;
-	int  top_bar_borderwidth;
-	int  top_bar_ypos;
-	int  screenshot_width;
-	int  screenshot_height;
-	int  top_bar_font;
-	HorAlignment speech_text_align;
-	int  auto_use_walkto_points;
-	int  inventory_greys_out;
-	int  skip_speech_specific_key;
-	int  abort_key;
-	int  fade_to_red;
-	int  fade_to_green;
-	int  fade_to_blue;
-	int  show_single_dialog_option;
-	int  keep_screen_during_instant_transition;
-	int  read_dialog_option_colour;
-	int  stop_dialog_at_end;
-	int  speech_portrait_placement; // speech portrait placement mode (automatic/custom)
-	int  speech_portrait_x; // a speech portrait x offset from corresponding screen side
-	int  speech_portrait_y; // a speech portrait y offset
-	int  speech_display_post_time_ms; // keep speech text/portrait on screen after text/voice has finished playing;
+	int  disable_antialiasing = 0;
+	int  text_speed_modifier = 0;
+	HorAlignment text_align = (HorAlignment)0;
+	int  speech_bubble_width = 0;
+	int  min_dialogoption_width = 0;
+	int  disable_dialog_parser = 0;
+	int  anim_background_speed = 0;  // the setting for this room
+	int  top_bar_backcolor = 0;
+	int  top_bar_textcolor = 0;
+	int  top_bar_bordercolor = 0;
+	int  top_bar_borderwidth = 0;
+	int  top_bar_ypos = 0;
+	int  screenshot_width = 0;
+	int  screenshot_height = 0;
+	int  top_bar_font = 0;
+	HorAlignment speech_text_align = (HorAlignment)0;
+	int  auto_use_walkto_points = 0;
+	int  inventory_greys_out = 0;
+	int  skip_speech_specific_key = 0;
+	int  abort_key = 0;
+	int  fade_to_red = 0;
+	int  fade_to_green = 0;
+	int  fade_to_blue = 0;
+	int  show_single_dialog_option = 0;
+	int  keep_screen_during_instant_transition = 0;
+	int  read_dialog_option_colour = 0;
+	int  stop_dialog_at_end = 0;
+	int  speech_portrait_placement = 0; // speech portrait placement mode (automatic/custom)
+	int  speech_portrait_x = 0; // a speech portrait x offset from corresponding screen side
+	int  speech_portrait_y = 0; // a speech portrait y offset
+	int  speech_display_post_time_ms = 0; // keep speech text/portrait on screen after text/voice has finished playing = 0;
 	// no speech animation is supposed to be played at this time
-	int  dialog_options_highlight_color; // The colour used for highlighted (hovered over) text in dialog options
+	int  dialog_options_highlight_color = 0; // The colour used for highlighted (hovered over) text in dialog options
 	int  reserved[GAME_STATE_RESERVED_INTS];  // make sure if a future version adds a var, it doesn't mess anything up
 	// ** up to here is referenced in the script "game." object
-	long  randseed;    // random seed
-	int   player_on_region;    // player's current region
-	int   screen_is_faded_out; // the screen is currently black
-	int   check_interaction_only;
-	int   bg_frame, bg_anim_delay;  // for animating backgrounds
-	int   music_vol_was;  // before the volume drop
-	short wait_counter;
-	short mboundx1, mboundx2, mboundy1, mboundy2;
-	int   fade_effect;
-	int   bg_frame_locked;
+	long  randseed = 0;    // random seed
+	int   player_on_region = 0;    // player's current region
+	int   screen_is_faded_out = 0; // the screen is currently black
+	int   check_interaction_only = 0;
+	int   bg_frame = 0, bg_anim_delay = 0;  // for animating backgrounds
+	int   music_vol_was = 0;  // before the volume drop
+	short wait_counter = 0;
+	short mboundx1 = 0, mboundx2 = 0, mboundy1 = 0, mboundy2 = 0;
+	int   fade_effect = 0;
+	int   bg_frame_locked = 0;
 	int   globalscriptvars[MAXGSVALUES];
-	int   cur_music_number, music_repeat;
-	int   music_master_volume;
-	int   digital_master_volume;
+	int   cur_music_number = 0, music_repeat = 0;
+	int   music_master_volume = 0;
+	int   digital_master_volume = 0;
 	char  walkable_areas_on[MAX_WALK_AREAS + 1];
-	short screen_flipped;
-	int   entered_at_x, entered_at_y, entered_edge;
-	int   want_speech;
-	int   cant_skip_speech;
+	short screen_flipped = 0;
+	int   entered_at_x = 0, entered_at_y = 0, entered_edge = 0;
+	int   want_speech = 0;
+	int   cant_skip_speech = 0;
 	int   script_timers[MAX_TIMERS];
-	int   sound_volume, speech_volume;
-	int   normal_font, speech_font;
-	char  key_skip_wait;
-	int   swap_portrait_lastchar;
-	int   swap_portrait_lastlastchar;
-	int   separate_music_lib;
-	int   in_conversation;
-	int   screen_tint;
-	int   num_parsed_words;
+	int   sound_volume = 0, speech_volume = 0;
+	int   normal_font = 0, speech_font = 0;
+	char  key_skip_wait = 0;
+	int   swap_portrait_lastchar = 0;
+	int   swap_portrait_lastlastchar = 0;
+	int   separate_music_lib = 0;
+	int   in_conversation = 0;
+	int   screen_tint = 0;
+	int   num_parsed_words = 0;
 	short parsed_words[MAX_PARSED_WORDS];
 	char  bad_parsed_word[100];
-	int   raw_color;
+	int   raw_color = 0;
 	int   raw_modified[MAX_ROOM_BGFRAMES];
-	Shared::PBitmap raw_drawing_surface;
+	Shared::PBitmap raw_drawing_surface = 0;
 	short filenumbers[MAXSAVEGAMES];
-	int   room_changes;
-	int   mouse_cursor_hidden;
-	int   silent_midi;
-	int   silent_midi_channel;
-	int   current_music_repeating;  // remember what the loop flag was when this music started
-	unsigned long shakesc_delay;  // unsigned long to match _G(loopcounter)
-	int   shakesc_amount, shakesc_length;
-	int   rtint_red, rtint_green, rtint_blue, rtint_level, rtint_light;
-	bool  rtint_enabled;
-	int   end_cutscene_music;
-	int   skip_until_char_stops;
-	int   get_loc_name_last_time;
-	int   get_loc_name_save_cursor;
-	int   restore_cursor_mode_to;
-	int   restore_cursor_image_to;
-	short music_queue_size;
+	int   room_changes = 0;
+	int   mouse_cursor_hidden = 0;
+	int   silent_midi = 0;
+	int   silent_midi_channel = 0;
+	int   current_music_repeating = 0;  // remember what the loop flag was when this music started
+	unsigned long shakesc_delay = 0;  // unsigned long to match _G(loopcounter)
+	int   shakesc_amount = 0, shakesc_length = 0;
+	int   rtint_red = 0, rtint_green = 0, rtint_blue = 0;
+	int   rtint_level = 0, rtint_light = 0;
+	bool  rtint_enabled = 0;
+	int   end_cutscene_music = 0;
+	int   skip_until_char_stops = 0;
+	int   get_loc_name_last_time = 0;
+	int   get_loc_name_save_cursor = 0;
+	int   restore_cursor_mode_to = 0;
+	int   restore_cursor_image_to = 0;
+	short music_queue_size = 0;
 	short music_queue[MAX_QUEUED_MUSIC];
-	short new_music_queue_size;
-	short crossfading_out_channel;
-	short crossfade_step;
-	short crossfade_out_volume_per_step;
-	short crossfade_initial_volume_out;
-	short crossfading_in_channel;
-	short crossfade_in_volume_per_step;
-	short crossfade_final_volume_in;
+	short new_music_queue_size = 0;
+	short crossfading_out_channel = 0;
+	short crossfade_step = 0;
+	short crossfade_out_volume_per_step = 0;
+	short crossfade_initial_volume_out = 0;
+	short crossfading_in_channel = 0;
+	short crossfade_in_volume_per_step = 0;
+	short crossfade_final_volume_in = 0;
 	QueuedAudioItem new_music_queue[MAX_QUEUED_MUSIC];
 	char  takeover_from[50];
 	char  playmp3file_name[PLAYMP3FILE_MAX_FILENAME_LEN];
 	char  globalstrings[MAXGLOBALSTRINGS][MAX_MAXSTRLEN];
 	char  lastParserEntry[MAX_MAXSTRLEN];
 	char  game_name[100];
-	int   ground_level_areas_disabled;
-	int   next_screen_transition;
-	int   gamma_adjustment;
-	short temporarily_turned_off_character;  // Hide Player Charactr ticked
-	short inv_backwards_compatibility;
-	int *gui_draw_order;
-	std::vector<AGS::Shared::String> do_once_tokens;
-	int   text_min_display_time_ms;
-	int   ignore_user_input_after_text_timeout_ms;
+	int   ground_level_areas_disabled = 0;
+	int   next_screen_transition = 0;
+	int   gamma_adjustment = 0;
+	short temporarily_turned_off_character = 0;  // Hide Player Charactr ticked
+	short inv_backwards_compatibility = 0;
+	int *gui_draw_order = 0;
+	std::vector<AGS::Shared::String> do_once_tokens = 0;
+	int   text_min_display_time_ms = 0;
+	int   ignore_user_input_after_text_timeout_ms = 0;
 	int   default_audio_type_volumes[MAX_AUDIO_TYPES];
 
 	// Dynamic custom property values for characters and items
@@ -234,16 +235,16 @@ struct GameState {
 	// Dynamic speech state
 	//
 	// Tells whether there is a voice-over played during current speech
-	bool  speech_has_voice;
+	bool  speech_has_voice = false;
 	// Tells whether the voice was played in blocking mode;
 	// atm blocking speech handles itself, and we only need to finalize
 	// non-blocking voice speech during game update; speech refactor would be
 	// required to get rid of this rule.
-	bool  speech_voice_blocking;
+	bool  speech_voice_blocking = false;
 	// Tells whether character speech stays on screen not animated for additional time
-	bool  speech_in_post_state;
+	bool  speech_in_post_state = false;
 
-	int shake_screen_yoff; // y offset of the shaking screen
+	int shake_screen_yoff = 0; // y offset of the shaking screen
 
 
 	GameState();
@@ -365,7 +366,7 @@ private:
 	void UpdateRoomCamera(int index);
 
 	// Defines if the room viewport should be adjusted to the room size automatically.
-	bool _isAutoRoomViewport;
+	bool _isAutoRoomViewport = false;
 	// Main viewport defines the rectangle of the drawn and interactable area
 	// in the most basic case it will be equal to the game size.
 	Viewport _mainViewport;
@@ -385,11 +386,11 @@ private:
 	std::vector<std::pair<ScriptCamera *, int32_t>> _scCameraRefs;
 
 	// Tells that the main viewport's position has changed since last game update
-	bool  _mainViewportHasChanged;
+	bool  _mainViewportHasChanged = false;
 	// Tells that room viewports need z-order resort
-	bool  _roomViewportZOrderChanged;
+	bool  _roomViewportZOrderChanged = false;
 
-	AGS_Clock::time_point _ignoreUserInputUntilTime;
+	AGS_Clock::time_point _ignoreUserInputUntilTime = 0;
 };
 
 // Converts legacy alignment type used in script API
diff --git a/engines/ags/engine/ac/object_cache.h b/engines/ags/engine/ac/object_cache.h
index 7f2d994e15..baa9c6df25 100644
--- a/engines/ags/engine/ac/object_cache.h
+++ b/engines/ags/engine/ac/object_cache.h
@@ -27,10 +27,11 @@ namespace AGS3 {
 
 // stores cached object info
 struct ObjectCache {
-	Shared::Bitmap *image;
-	int   sppic;
-	short tintredwas, tintgrnwas, tintbluwas, tintamntwas, tintlightwas;
-	short lightlevwas, mirroredWas, zoomWas;
+	Shared::Bitmap *image = nullptr;
+	int   sppic = 0;
+	short tintredwas = 0, tintgrnwas = 0, tintbluwas = 0;
+	short tintamntwas = 0, tintlightwas = 0;
+	short lightlevwas = 0, mirroredWas = 0, zoomWas = 0;
 	// The following are used to determine if the character has moved
 	int   xwas, ywas;
 };
diff --git a/engines/ags/engine/ac/room_status.h b/engines/ags/engine/ac/room_status.h
index b5831ece52..30ec22965b 100644
--- a/engines/ags/engine/ac/room_status.h
+++ b/engines/ags/engine/ac/room_status.h
@@ -43,12 +43,12 @@ using AGS::Shared::Interaction;
 // This struct is saved in the save games - it contains everything about
 // a room that could change
 struct RoomStatus {
-	int   beenhere;
-	int   numobj;
+	int   beenhere = 0;
+	int   numobj = 0;
 	RoomObject obj[MAX_ROOM_OBJECTS];
 	short flagstates[MAX_FLAGS];
-	int   tsdatasize;
-	char *tsdata;
+	int   tsdatasize = 0;
+	char *tsdata = nullptr;
 	Interaction intrHotspot[MAX_ROOM_HOTSPOTS];
 	Interaction intrObject[MAX_ROOM_OBJECTS];
 	Interaction intrRegion[MAX_ROOM_REGIONS];
diff --git a/engines/ags/engine/gui/animating_gui_button.h b/engines/ags/engine/gui/animating_gui_button.h
index cef6c29523..c9f32ac68b 100644
--- a/engines/ags/engine/gui/animating_gui_button.h
+++ b/engines/ags/engine/gui/animating_gui_button.h
@@ -37,10 +37,10 @@ using namespace AGS; // FIXME later
 
 struct AnimatingGUIButton {
 	// index into _GP(guibuts) array, GUI, button
-	short buttonid, ongui, onguibut;
+	short buttonid = 0, ongui = 0, onguibut = 0;
 	// current animation status
-	short view, loop, frame;
-	short speed, repeat, wait;
+	short view = 0, loop = 0, frame = 0;
+	short speed = 0, repeat = 0, wait = 0;
 
 	void ReadFromFile(Shared::Stream *in);
 	void WriteToFile(Shared::Stream *out);
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 8a9f85e320..c49afe64d0 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -102,6 +102,11 @@ Globals *g_globals;
 Globals::Globals() {
 	g_globals = this;
 
+	// Allegro globals
+	Common::fill((byte *)&_black_palette, (byte *)&_black_palette + PAL_SIZE, 0);
+	Common::fill((byte *)&_current_palette, (byte *)&_current_palette + PAL_SIZE, 0);
+	Common::fill((byte *)&_prev_current_palette, (byte *)&_prev_current_palette + PAL_SIZE, 0);
+
 	// ags_plugin.cpp globals
 	_glVirtualScreenWrap = new AGS::Shared::Bitmap();
 
@@ -333,7 +338,7 @@ Globals::Globals() {
 	Common::fill(_walkBehindRight, _walkBehindRight + MAX_WALK_BEHINDS, 0);
 	Common::fill(_walkBehindBottom, _walkBehindBottom + MAX_WALK_BEHINDS, 0);
 	Common::fill(_walkBehindBitmap, _walkBehindBitmap + MAX_WALK_BEHINDS,
-	             (AGS::Engine::IDriverDependantBitmap *)nullptr);
+		(AGS::Engine::IDriverDependantBitmap *)nullptr);
 }
 
 Globals::~Globals() {
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index abd71c0328..81a1189056 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -218,7 +218,7 @@ public:
 	volatile int _sys_mouse_x = 0; // mouse x position
 	volatile int _sys_mouse_y = 0; // mouse y position
 	volatile int _sys_mouse_z = 0; // mouse wheel position
-	volatile int _freeze_mouse_flag;
+	volatile int _freeze_mouse_flag = 0;
 
 	int _mouse_button_state = 0;
 	int _mouse_accum_button_state = 0;
@@ -429,7 +429,7 @@ public:
 	bool _facetalk_qfg4_override_placement_y = false;
 
 	// lip-sync speech settings
-	int _loops_per_character, _text_lips_offset, _char_speaking = -1;
+	int _loops_per_character = 0, _text_lips_offset = 0, _char_speaking = -1;
 	int _char_thinking = -1;
 	const char *_text_lips_text = nullptr;
 	SpeechLipSyncLine *_splipsync = nullptr;
@@ -508,7 +508,7 @@ public:
 	 * @{
 	 */
 
-	DialogTopic *_dialog;
+	DialogTopic *_dialog = nullptr;
 	ScriptDialogOptionsRendering *_ccDialogOptionsRendering;
 	ScriptDrawingSurface *_dialogOptionsRenderingSurface = nullptr;
 
@@ -729,7 +729,7 @@ public:
 	bool _abort_engine = false;
 	AGSPlatformDriver *_platform = nullptr;
 
-	RoomObject *_objs;
+	RoomObject *_objs = nullptr;
 	RoomStatus *_croom = nullptr;
 
 	volatile int _switching_away_from_game = 0;
diff --git a/engines/ags/shared/ac/game_struct_defines.h b/engines/ags/shared/ac/game_struct_defines.h
index c6099f7cc0..d7259ca908 100644
--- a/engines/ags/shared/ac/game_struct_defines.h
+++ b/engines/ags/shared/ac/game_struct_defines.h
@@ -230,17 +230,17 @@ struct SpriteInfo {
 // multiple lines, and similar cases.
 struct FontInfo {
 	// General font's loading and rendering flags
-	uint32_t      Flags;
+	uint32_t      Flags = 0;
 	// Font size, in points (basically means pixels in AGS)
-	int           SizePt;
+	int           SizePt = 0;
 	// Factor to multiply base font size by
-	int           SizeMultiplier;
+	int           SizeMultiplier = 0;
 	// Outlining font index, or auto-outline flag
-	char          Outline;
+	char          Outline = 0;
 	// Custom vertical render offset, used mainly for fixing broken fonts
-	int           YOffset;
+	int           YOffset = 0;
 	// custom line spacing between two lines of text (0 = use font height)
-	int           LineSpacing;
+	int           LineSpacing = 0;
 
 	FontInfo();
 };


Commit: c94255481016f462fdb5bc7557a16d2e3066674a
    https://github.com/scummvm/scummvm/commit/c94255481016f462fdb5bc7557a16d2e3066674a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:52-07:00

Commit Message:
AGS: Fixes for calling plugins

Changed paths:
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/script/script_runtime.cpp
    engines/ags/plugins/ags_plugin.h


diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 1c0e3abef2..52ea5118c4 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -79,6 +79,7 @@
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -226,7 +227,12 @@ String get_save_game_filename(int slotNum) {
 }
 
 String get_save_game_path(int slotNum) {
+#if AGS_PLATFORM_SCUMMVM
+	return Common::String::format("%s%s", SAVE_FOLDER_PREFIX,
+		::AGS::g_vm->getSaveStateName(slotNum).c_str());
+#else
 	return Path::ConcatPaths(_G(saveGameDirectory), get_save_game_filename(slotNum));
+#endif
 }
 
 // Convert a path possibly containing path tags into acceptable save path
@@ -280,6 +286,9 @@ bool SetCustomSaveParent(const String &path) {
 }
 
 bool SetSaveGameDirectoryPath(const char *newFolder, bool explicit_path) {
+#if AGS_PLATFORM_SCUMMVM
+	return false;
+#else
 	if (!newFolder || newFolder[0] == 0)
 		newFolder = ".";
 	String newSaveGameDir;
@@ -320,6 +329,7 @@ bool SetSaveGameDirectoryPath(const char *newFolder, bool explicit_path) {
 
 	_G(saveGameDirectory) = newSaveGameDir;
 	return true;
+#endif
 }
 
 int Game_SetSaveGameDirectory(const char *newFolder) {
diff --git a/engines/ags/engine/script/script_runtime.cpp b/engines/ags/engine/script/script_runtime.cpp
index f82f2dd85d..38cdf39031 100644
--- a/engines/ags/engine/script/script_runtime.cpp
+++ b/engines/ags/engine/script/script_runtime.cpp
@@ -41,6 +41,8 @@
 #include "ags/engine/ac/dynobj/cc_dynamic_array.h"
 #include "ags/engine/script/system_imports.h"
 #include "ags/engine/ac/statobj/static_object.h"
+#include "ags/plugins/ags_plugin.h"
+#include "ags/plugins/plugin_base.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -160,99 +162,33 @@ int call_function(intptr_t addr, const RuntimeScriptValue *object, int numparm,
 		}
 	}
 
-	//
-	// AN IMPORTANT NOTE ON PARAM TYPE
-	// of 2012-11-10
-	//
-	//// NOTE of 2012-12-20:
-	//// Everything said below is applicable only for calling
-	//// exported plugin functions.
-	//
-	// Here we are sending parameters of type intptr_t to registered
-	// function of unknown kind. Intptr_t is 32-bit for x32 build and
-	// 64-bit for x64 build.
-	// The exported functions usually have two types of parameters:
-	// pointer and 'int' (32-bit). For x32 build those two have the
-	// same size, but for x64 build first has 64-bit size while the
-	// second remains 32-bit.
-	// In formal case that would cause 'overflow' - function will
-	// receive more data than needed (written to stack), with some
-	// values shifted further by 32 bits.
-	//
-	// Upon testing, however, it was revealed that AMD64 processor,
-	// the only platform we support x64 Linux AGS build on right now,
-	// treats all the function parameters pushed to stack as 64-bit
-	// values (few first parameters are sent via registers, and hence
-	// are least concern anyway). Therefore, no 'overflow' occurs,
-	// and 64-bit values are being effectively truncated to 32-bit
-	// integers in the callee.
-	//
-	// Since this is still quite unreliable, this should be
-	// reimplemented when there's enough free time available for
-	// developers both for coding & testing.
-	//
-	// Most basic idea is to pass array of RuntimeScriptValue
-	// objects (that hold type description) and get same RSV as a
-	// return result. Keep in mind, though, that this solution will
-	// require fixing ALL exported functions, so a good amount of
-	// time and energy should be allocated for this task.
-	//
+	// AN IMPORTANT NOTE ON PARAMS
+	// The original AGS interpreter did a bunch of dodgy function pointers with
+	// varying numbers of parameters, which were all int64_t. To simply matters
+	// now that we only supported plugins implemented in code, and not DLLs,
+	// we use a simplified Common::Array containing the parameters and result
 
-	switch (numparm) {
-	case 0: {
-		int (*fparam)();
-		fparam = (int (*)())addr;
-		return fparam();
-	}
-	case 1: {
-		int (*fparam)(intptr_t);
-		fparam = (int (*)(intptr_t))addr;
-		return fparam(parm_value[0]);
-	}
-	case 2: {
-		int (*fparam)(intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1]);
-	}
-	case 3: {
-		int (*fparam)(intptr_t, intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1], parm_value[2]);
-	}
-	case 4: {
-		int (*fparam)(intptr_t, intptr_t, intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t, intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1], parm_value[2], parm_value[3]);
-	}
-	case 5: {
-		int (*fparam)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1], parm_value[2], parm_value[3], parm_value[4]);
-	}
-	case 6: {
-		int (*fparam)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1], parm_value[2], parm_value[3], parm_value[4], parm_value[5]);
-	}
-	case 7: {
-		int (*fparam)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1], parm_value[2], parm_value[3], parm_value[4], parm_value[5], parm_value[6]);
-	}
-	case 8: {
-		int (*fparam)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1], parm_value[2], parm_value[3], parm_value[4], parm_value[5], parm_value[6], parm_value[7]);
-	}
-	case 9: {
-		int (*fparam)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t);
-		fparam = (int (*)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t))addr;
-		return fparam(parm_value[0], parm_value[1], parm_value[2], parm_value[3], parm_value[4], parm_value[5], parm_value[6], parm_value[7], parm_value[8]);
-	}
-	}
+	if (numparm > 9) {
+		cc_error("too many arguments in call to function");
+		return -1;
+	} else {
+		// Build the parameters
+		ScriptMethodParams params;
+		for (int i = 0; i < numparm; ++i)
+			params.push_back(parm_value[i]);
+
+		// Call the method
+		Plugins::PluginMethod fparam = (Plugins::PluginMethod)addr;
+		fparam(params);
 
-	cc_error("too many arguments in call to function");
-	return -1;
+		// TODO: Though some script methods return pointers, the call_function only
+		// supports a 32-bit result. In case they're actually used by any game, the
+		// guard below will throw a wobbly if they're more than 32-bits
+		if ((int64)params._result._ptr > 0xffffffff)
+			error("Uhandled 64-bit pointer result from plugin method call");
+
+		return params._result;
+	}
 }
 
 } // namespace AGS3
diff --git a/engines/ags/plugins/ags_plugin.h b/engines/ags/plugins/ags_plugin.h
index 4affca4f28..03a63746f4 100644
--- a/engines/ags/plugins/ags_plugin.h
+++ b/engines/ags/plugins/ags_plugin.h
@@ -38,7 +38,7 @@ namespace AGS3 {
 
 class ScriptMethodParams : public Common::Array<intptr_t> {
 public:
-NumberPtr _result;
+	NumberPtr _result;
 };
 
 // If the plugin isn't using DDraw, don't require the headers
@@ -84,40 +84,40 @@ unsigned char padding;
 };
 
 struct AGSGameOptions {
-int32 score;      // player's current score
-int32 usedmode;   // set by ProcessClick to last cursor mode used
-int32 disabled_user_interface;  // >0 while in cutscene/etc
-int32 gscript_timer;    // obsolete
-int32 debug_mode;       // whether we're in debug mode
-int32 globalvars[50];   // obsolete
-int32 messagetime;      // time left for auto-remove messages
-int32 usedinv;          // inventory item last used
-int32 inv_top, inv_numdisp, inv_numorder, inv_numinline;
-int32 text_speed;       // how quickly text is removed
-int32 sierra_inv_color; // background used to paint defualt inv window
-int32 talkanim_speed;   // animation speed of talking anims
-int32 inv_item_wid, inv_item_hit;  // set by SetInvDimensions
-int32 speech_text_shadow;         // colour of outline fonts (default black)
-int32 swap_portrait_side;         // sierra-style speech swap sides
-int32 speech_textwindow_gui;      // textwindow used for sierra-style speech
-int32 follow_change_room_timer;   // delay before moving following characters into new room
-int32 totalscore;           // maximum possible score
-int32 skip_display;         // how the user can skip normal Display windows
-int32 no_multiloop_repeat;  // for backwards compatibility
-int32 roomscript_finished;  // on_call finished in room
-int32 used_inv_on;          // inv item they clicked on
-int32 no_textbg_when_voice; // no textwindow bgrnd when voice speech is used
-int32 max_dialogoption_width; // max width of dialog options text window
-int32 no_hicolor_fadein;      // fade out but instant in for hi-color
-int32 bgspeech_game_speed;    // is background speech relative to game speed
-int32 bgspeech_stay_on_display; // whether to remove bg speech when DisplaySpeech is used
-int32 unfactor_speech_from_textlength; // remove "&10" when calculating time for text to stay
-int32 mp3_loop_before_end;    // loop this time before end of track (ms)
-int32 speech_music_drop;      // how much to drop music volume by when speech is played
-int32 in_cutscene;            // we are between a StartCutscene and EndCutscene
-int32 fast_forward;           // player has elected to skip cutscene
-int32 room_width;             // width of current room
-int32 room_height;            // height of current room
+	int32 score;      // player's current score
+	int32 usedmode;   // set by ProcessClick to last cursor mode used
+	int32 disabled_user_interface;  // >0 while in cutscene/etc
+	int32 gscript_timer;    // obsolete
+	int32 debug_mode;       // whether we're in debug mode
+	int32 globalvars[50];   // obsolete
+	int32 messagetime;      // time left for auto-remove messages
+	int32 usedinv;          // inventory item last used
+	int32 inv_top, inv_numdisp, inv_numorder, inv_numinline;
+	int32 text_speed;       // how quickly text is removed
+	int32 sierra_inv_color; // background used to paint defualt inv window
+	int32 talkanim_speed;   // animation speed of talking anims
+	int32 inv_item_wid, inv_item_hit;  // set by SetInvDimensions
+	int32 speech_text_shadow;         // colour of outline fonts (default black)
+	int32 swap_portrait_side;         // sierra-style speech swap sides
+	int32 speech_textwindow_gui;      // textwindow used for sierra-style speech
+	int32 follow_change_room_timer;   // delay before moving following characters into new room
+	int32 totalscore;           // maximum possible score
+	int32 skip_display;         // how the user can skip normal Display windows
+	int32 no_multiloop_repeat;  // for backwards compatibility
+	int32 roomscript_finished;  // on_call finished in room
+	int32 used_inv_on;          // inv item they clicked on
+	int32 no_textbg_when_voice; // no textwindow bgrnd when voice speech is used
+	int32 max_dialogoption_width; // max width of dialog options text window
+	int32 no_hicolor_fadein;      // fade out but instant in for hi-color
+	int32 bgspeech_game_speed;    // is background speech relative to game speed
+	int32 bgspeech_stay_on_display; // whether to remove bg speech when DisplaySpeech is used
+	int32 unfactor_speech_from_textlength; // remove "&10" when calculating time for text to stay
+	int32 mp3_loop_before_end;    // loop this time before end of track (ms)
+	int32 speech_music_drop;      // how much to drop music volume by when speech is played
+	int32 in_cutscene;            // we are between a StartCutscene and EndCutscene
+	int32 fast_forward;           // player has elected to skip cutscene
+	int32 room_width;             // width of current room
+	int32 room_height;            // height of current room
 };
 
 // AGSCharacter.flags
@@ -131,33 +131,33 @@ int32 room_height;            // height of current room
 #define CHF_NOWALKBEHINDS   0x80
 
 struct AGSCharacter {
-int32 defview;
-int32 talkview;
-int32 view;
-int32 room, prevroom;
-int32 x, y, wait;
-int32 flags;
-short following;
-short followinfo;
-int32 idleview;           // the loop will be randomly picked
-short idletime, idleleft; // num seconds idle before playing anim
-short transparency;       // if character is transparent
-short baseline;
-int32 activeinv;
-int32 talkcolor;
-int32 thinkview;
-int32 reserved[2];
-short walkspeed_y, pic_yoffs;
-int32 z;
-int32 reserved2[5];
-short loop, frame;
-short walking, animating;
-short walkspeed, animspeed;
-short inv[301];
-short actx, acty;
-char  name[40];
-char  scrname[20];
-char  on;
+	int32 defview = 0;
+	int32 talkview = 0;
+	int32 view = 0;
+	int32 room = 0, prevroom = 0;
+	int32 x = 0, y = 0, wait = 0;
+	int32 flags = 0;
+	short following = 0;
+	short followinfo = 0;
+	int32 idleview = 0;           // the loop will be randomly picked
+	short idletime = 0, idleleft = 0; // num seconds idle before playing anim
+	short transparency = 0;       // if character is transparent
+	short baseline = 0;
+	int32 activeinv = 0;
+	int32 talkcolor = 0;
+	int32 thinkview = 0;
+	int32 reserved[2];
+	short walkspeed_y = 0, pic_yoffs = 0;
+	int32 z = 0;
+	int32 reserved2[5];
+	short loop = 0, frame = 0;
+	short walking = 0, animating = 0;
+	short walkspeed = 0, animspeed = 0;
+	short inv[301];
+	short actx = 0, acty = 0;
+	char  name[40];
+	char  scrname[20];
+	char  on = 0;
 };
 
 // AGSObject.flags
@@ -165,29 +165,29 @@ char  on;
 #define OBJF_NOWALKBEHINDS 2  // ignore walk-behinds
 
 struct AGSObject {
-int32 x, y;
-int32 transparent;    // current transparency setting
-int32 reserved[4];
-short num;            // sprite slot number
-short baseline;       // <=0 to use Y co-ordinate; >0 for specific baseline
-short view, loop, frame; // only used to track animation - 'num' holds the current sprite
-short wait, moving;
-char  cycling;        // is it currently animating?
-char  overall_speed;
-char  on;
-char  flags;
+	int32 x = 0, y = 0;
+	int32 transparent = 0;    // current transparency setting
+	int32 reserved[4];
+	short num = 0;            // sprite slot number
+	short baseline = 0;       // <=0 to use Y co-ordinate; >0 for specific baseline
+	short view = 0, loop = 0, frame = 0; // only used to track animation - 'num' holds the current sprite
+	short wait = 0, moving = 0;
+	char  cycling = 0;        // is it currently animating?
+	char  overall_speed = 0;
+	char  on = 0;
+	char  flags = 0;
 };
 
 // AGSViewFrame.flags
 #define FRAF_MIRRORED  1  // flipped left to right
 
 struct AGSViewFrame {
-int32 pic;            // sprite slot number
-short xoffs, yoffs;
-short speed;
-int32 flags;
-int32 sound;          // play sound when this frame comes round
-int32 reserved_for_future[2];
+	int32 pic = 0;            // sprite slot number
+	short xoffs = 0, yoffs = 0;
+	short speed = 0;
+	int32 flags = 0;
+	int32 sound = 0;          // play sound when this frame comes round
+	int32 reserved_for_future[2];
 };
 
 // AGSMouseCursor.flags
@@ -197,30 +197,30 @@ int32 reserved_for_future[2];
 #define MCF_ONLYANIMOVERHOTSPOT 8
 
 struct AGSMouseCursor {
-int32 pic;            // sprite slot number
-short hotx, hoty;     // x,y hotspot co-ordinates
-short view;           // view (for animating cursors) or -1
-char  name[10];       // name of cursor mode
-char  flags;          // MCF_flags above
+	int32 pic = 0;            // sprite slot number
+	short hotx = 0, hoty = 0; // x,y hotspot co-ordinates
+	short view = 0;           // view (for animating cursors) or -1
+	char  name[10];           // name of cursor mode
+	char  flags = 0;          // MCF_flags above
 };
 
 // The editor-to-plugin interface
 class IAGSEditor {
 public:
-int32 version;
-int32 pluginId;   // used internally, do not touch this
+	int32 version = 0;
+	int32 pluginId = 0;   // used internally, do not touch this
 
 public:
-virtual ~IAGSEditor() {}
-
-// get the HWND of the main editor frame
-AGSIFUNC(HWND) GetEditorHandle();
-// get the HWND of the current active window
-AGSIFUNC(HWND) GetWindowHandle();
-// add some script to the default header
-AGSIFUNC(void) RegisterScriptHeader(const char *header);
-// de-register a script header (pass same pointer as when added)
-AGSIFUNC(void) UnregisterScriptHeader(const char *header);
+	virtual ~IAGSEditor() {}
+
+	// get the HWND of the main editor frame
+	AGSIFUNC(HWND) GetEditorHandle();
+	// get the HWND of the current active window
+	AGSIFUNC(HWND) GetWindowHandle();
+	// add some script to the default header
+	AGSIFUNC(void) RegisterScriptHeader(const char *header);
+	// de-register a script header (pass same pointer as when added)
+	AGSIFUNC(void) UnregisterScriptHeader(const char *header);
 };
 
 
@@ -270,313 +270,313 @@ AGSIFUNC(void) UnregisterScriptHeader(const char *header);
 
 class IAGSScriptManagedObject {
 public:
-// when a ref count reaches 0, this is called with the address
-// of the object. Return 1 to remove the object from memory, 0 to
-// leave it
-virtual int Dispose(const char *address, bool force) = 0;
-// return the type name of the object
-virtual const char *GetType() = 0;
-// serialize the object into BUFFER (which is BUFSIZE bytes)
-// return number of bytes used
-virtual int Serialize(const char *address, char *buffer, int bufsize) = 0;
+	// when a ref count reaches 0, this is called with the address
+	// of the object. Return 1 to remove the object from memory, 0 to
+	// leave it
+	virtual int Dispose(const char *address, bool force) = 0;
+	// return the type name of the object
+	virtual const char *GetType() = 0;
+	// serialize the object into BUFFER (which is BUFSIZE bytes)
+	// return number of bytes used
+	virtual int Serialize(const char *address, char *buffer, int bufsize) = 0;
 protected:
-IAGSScriptManagedObject() {
-}
-virtual ~IAGSScriptManagedObject() {
-}
+	IAGSScriptManagedObject() {
+	}
+	virtual ~IAGSScriptManagedObject() {
+	}
 };
 
 class IAGSManagedObjectReader {
 public:
-virtual void Unserialize(int key, const char *serializedData, int dataSize) = 0;
+	virtual void Unserialize(int key, const char *serializedData, int dataSize) = 0;
 protected:
-IAGSManagedObjectReader() {
-}
-virtual ~IAGSManagedObjectReader() {
-}
+	IAGSManagedObjectReader() {
+	}
+	virtual ~IAGSManagedObjectReader() {
+	}
 };
 
 class IAGSFontRenderer {
 public:
-virtual bool LoadFromDisk(int fontNumber, int fontSize) = 0;
-virtual void FreeMemory(int fontNumber) = 0;
-virtual bool SupportsExtendedCharacters(int fontNumber) = 0;
-virtual int GetTextWidth(const char *text, int fontNumber) = 0;
-virtual int GetTextHeight(const char *text, int fontNumber) = 0;
-virtual void RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) = 0;
-virtual void AdjustYCoordinateForFont(int *ycoord, int fontNumber) = 0;
-virtual void EnsureTextValidForFont(char *text, int fontNumber) = 0;
+	virtual bool LoadFromDisk(int fontNumber, int fontSize) = 0;
+	virtual void FreeMemory(int fontNumber) = 0;
+	virtual bool SupportsExtendedCharacters(int fontNumber) = 0;
+	virtual int GetTextWidth(const char *text, int fontNumber) = 0;
+	virtual int GetTextHeight(const char *text, int fontNumber) = 0;
+	virtual void RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) = 0;
+	virtual void AdjustYCoordinateForFont(int *ycoord, int fontNumber) = 0;
+	virtual void EnsureTextValidForFont(char *text, int fontNumber) = 0;
 protected:
-IAGSFontRenderer() {
-}
-virtual ~IAGSFontRenderer() {
-}
+	IAGSFontRenderer() {
+	}
+	virtual ~IAGSFontRenderer() {
+	}
 };
 
 
 struct AGSRenderMatrixes {
-float WorldMatrix[16];
-float ViewMatrix[16];
-float ProjMatrix[16];
+	float WorldMatrix[16];
+	float ViewMatrix[16];
+	float ProjMatrix[16];
 };
 
 // Render stage description
 struct AGSRenderStageDesc {
-// Which version of the plugin interface the struct corresponds to;
-// this field must be filled by a plugin before passing the struct into the engine!
-int Version;
-// Stage's matrixes, for 3D rendering: Projection, World and View
-AGSRenderMatrixes Matrixes;
+	// Which version of the plugin interface the struct corresponds to;
+	// this field must be filled by a plugin before passing the struct into the engine!
+	int Version = 0;
+	// Stage's matrixes, for 3D rendering: Projection, World and View
+	AGSRenderMatrixes Matrixes;
 };
 
 
 // The plugin-to-engine interface
 class IAGSEngine {
 public:
-int32 version;
-int32 pluginId;   // used internally, do not touch
+	int32 version = 0;
+	int32 pluginId = 0;   // used internally, do not touch
 
 public:
-virtual ~IAGSEngine() {}
-
-// quit the game
-AGSIFUNC(void) AbortGame(const char *reason);
-// get engine version
-AGSIFUNC(const char *) GetEngineVersion();
-// register a script function with the system
-AGSIFUNC(void) RegisterScriptFunction(const char *name, void *address);
-#ifdef WINDOWS_VERSION
-// get game window handle
-AGSIFUNC(HWND) GetWindowHandle();
-// get reference to main DirectDraw interface
-AGSIFUNC(LPDIRECTDRAW2) GetDirectDraw2();
-// get the DDraw surface associated with a bitmap
-AGSIFUNC(LPDIRECTDRAWSURFACE2) GetBitmapSurface(BITMAP *);
-#endif
-// get a reference to the screen bitmap
-AGSIFUNC(BITMAP *) GetScreen();
-
-// *** BELOW ARE INTERFACE VERSION 2 AND ABOVE ONLY
-// ask the engine to call back when a certain event happens
-AGSIFUNC(void) RequestEventHook(int32 event);
-// get the options data saved in the editor
-AGSIFUNC(int)  GetSavedData(char *buffer, int32 bufsize);
-
-// *** BELOW ARE INTERFACE VERSION 3 AND ABOVE ONLY
-// get the virtual screen
-AGSIFUNC(BITMAP *) GetVirtualScreen();
-// write text to the screen in the specified font and colour
-AGSIFUNC(void) DrawText(int32 x, int32 y, int32 font, int32 color, const char *text);
-// get screen dimensions
-AGSIFUNC(void) GetScreenDimensions(int32 *width, int32 *height, int32 *coldepth);
-// get screen surface pitch
-AGSIFUNC(int) GetBitmapPitch(BITMAP *);
-// get screen surface to draw on
-AGSIFUNC(uint8 *) GetRawBitmapSurface(BITMAP *);
-// release the surface
-AGSIFUNC(void) ReleaseBitmapSurface(BITMAP *);
-// get the current mouse co-ordinates
-AGSIFUNC(void) GetMousePosition(int32 *x, int32 *y);
-
-// *** BELOW ARE INTERFACE VERSION 4 AND ABOVE ONLY
-// get the current room number
-AGSIFUNC(int)  GetCurrentRoom();
-// get the number of background scenes in this room
-AGSIFUNC(int)  GetNumBackgrounds();
-// get the current background frame
-AGSIFUNC(int)  GetCurrentBackground();
-// get a background scene bitmap
-AGSIFUNC(BITMAP *) GetBackgroundScene(int32);
-// get dimensions of a bitmap
-AGSIFUNC(void) GetBitmapDimensions(BITMAP *bmp, int32 *width, int32 *height, int32 *coldepth);
-
-// *** BELOW ARE INTERFACE VERSION 5 AND ABOVE ONLY
-// similar to fwrite - buffer, size, filehandle
-AGSIFUNC(int)  FWrite(void *, int32, int32);
-// similar to fread - buffer, size, filehandle
-AGSIFUNC(int)  FRead(void *, int32, int32);
-// print text, wrapping as usual
-AGSIFUNC(void) DrawTextWrapped(int32 x, int32 y, int32 width, int32 font, int32 color, const char *text);
-// set the current active 'screen'
-AGSIFUNC(void) SetVirtualScreen(BITMAP *);
-// look up a word in the parser dictionary
-AGSIFUNC(int)  LookupParserWord(const char *word);
-// draw a bitmap to the active screen
-AGSIFUNC(void) BlitBitmap(int32 x, int32 y, BITMAP *, int32 masked);
-// update the mouse and music
-AGSIFUNC(void) PollSystem();
-
-// *** BELOW ARE INTERFACE VERSION 6 AND ABOVE ONLY
-// get number of characters in game
-AGSIFUNC(int)  GetNumCharacters();
-// get reference to specified character struct
-AGSIFUNC(AGSCharacter *) GetCharacter(int32);
-// get reference to game struct
-AGSIFUNC(AGSGameOptions *) GetGameOptions();
-// get reference to current palette
-AGSIFUNC(AGSColor *) GetPalette();
-// update palette
-AGSIFUNC(void) SetPalette(int32 start, int32 finish, AGSColor *);
-
-// *** BELOW ARE INTERFACE VERSION 7 AND ABOVE ONLY
-// get the current player character
-AGSIFUNC(int)  GetPlayerCharacter();
-// adjust to main viewport co-ordinates
-AGSIFUNC(void) RoomToViewport(int32 *x, int32 *y);
-// adjust from main viewport co-ordinates (ignores viewport bounds)
-AGSIFUNC(void) ViewportToRoom(int32 *x, int32 *y);
-// number of objects in current room
-AGSIFUNC(int)  GetNumObjects();
-// get reference to specified object
-AGSIFUNC(AGSObject *) GetObject(int32);
-// get sprite graphic
-AGSIFUNC(BITMAP *) GetSpriteGraphic(int32);
-// create a new blank bitmap
-AGSIFUNC(BITMAP *) CreateBlankBitmap(int32 width, int32 height, int32 coldep);
-// free a created bitamp
-AGSIFUNC(void) FreeBitmap(BITMAP *);
-
-// *** BELOW ARE INTERFACE VERSION 8 AND ABOVE ONLY
-// get one of the room area masks
-AGSIFUNC(BITMAP *) GetRoomMask(int32);
-
-// *** BELOW ARE INTERFACE VERSION 9 AND ABOVE ONLY
-// get a particular view frame
-AGSIFUNC(AGSViewFrame *) GetViewFrame(int32 view, int32 loop, int32 frame);
-// get the walk-behind baseline of a specific WB area
-AGSIFUNC(int)    GetWalkbehindBaseline(int32 walkbehind);
-// get the address of a script function
-AGSIFUNC(void *) GetScriptFunctionAddress(const char *funcName);
-// get the transparent colour of a bitmap
-AGSIFUNC(int)    GetBitmapTransparentColor(BITMAP *);
-// get the character scaling level at a particular point
-AGSIFUNC(int)    GetAreaScaling(int32 x, int32 y);
-// equivalent to the text script function
-AGSIFUNC(int)    IsGamePaused();
-
-// *** BELOW ARE INTERFACE VERSION 10 AND ABOVE ONLY
-// get the raw pixel value to use for the specified AGS colour
-AGSIFUNC(int)    GetRawPixelColor(int32 color);
-
-// *** BELOW ARE INTERFACE VERSION 11 AND ABOVE ONLY
-// get the width / height of the specified sprite
-AGSIFUNC(int)    GetSpriteWidth(int32);
-AGSIFUNC(int)    GetSpriteHeight(int32);
-// get the dimensions of the specified string in the specified font
-AGSIFUNC(void)   GetTextExtent(int32 font, const char *text, int32 *width, int32 *height);
-// print a message to the debug console
-AGSIFUNC(void)   PrintDebugConsole(const char *text);
-// play a sound on the specified channel
-AGSIFUNC(void)   PlaySoundChannel(int32 channel, int32 soundType, int32 volume, int32 loop, const char *filename);
-// same as text script function
-AGSIFUNC(int)    IsChannelPlaying(int32 channel);
-
-// *** BELOW ARE INTERFACE VERSION 12 AND ABOVE ONLY
-// invalidate a region of the virtual screen
-AGSIFUNC(void)   MarkRegionDirty(int32 left, int32 top, int32 right, int32 bottom);
-// get mouse cursor details
-AGSIFUNC(AGSMouseCursor *) GetMouseCursor(int32 cursor);
-// get the various components of a pixel
-AGSIFUNC(void)   GetRawColorComponents(int32 coldepth, int32 color, int32 *red, int32 *green, int32 *blue, int32 *alpha);
-// make a pixel colour from the supplied components
-AGSIFUNC(int)    MakeRawColorPixel(int32 coldepth, int32 red, int32 green, int32 blue, int32 alpha);
-// get whether the font is TTF or SCI
-AGSIFUNC(int)    GetFontType(int32 fontNum);
-// create a new dynamic sprite slot
-AGSIFUNC(int)    CreateDynamicSprite(int32 coldepth, int32 width, int32 height);
-// free a created dynamic sprite
-AGSIFUNC(void)   DeleteDynamicSprite(int32 slot);
-// check if a sprite has an alpha channel
-AGSIFUNC(int)    IsSpriteAlphaBlended(int32 slot);
-
-// *** BELOW ARE INTERFACE VERSION 13 AND ABOVE ONLY
-// un-request an event, requested earlier with RequestEventHook
-AGSIFUNC(void)   UnrequestEventHook(int32 event);
-// draw a translucent bitmap to the active screen
-AGSIFUNC(void)   BlitSpriteTranslucent(int32 x, int32 y, BITMAP *, int32 trans);
-// draw a sprite to the screen, but rotated around its centre
-AGSIFUNC(void)   BlitSpriteRotated(int32 x, int32 y, BITMAP *, int32 angle);
-
-// *** BELOW ARE INTERFACE VERSION 14 AND ABOVE ONLY
-#ifdef WINDOWS_VERSION
-// get reference to main DirectSound interface
-AGSIFUNC(LPDIRECTSOUND) GetDirectSound();
-#endif
-// disable AGS sound engine
-AGSIFUNC(void)   DisableSound();
-// check whether a script function can be run now
-AGSIFUNC(int)    CanRunScriptFunctionNow();
-// call a user-defined script function
-AGSIFUNC(int)    CallGameScriptFunction(const char *name, int32 globalScript, int32 numArgs, long arg1 = 0, long arg2 = 0, long arg3 = 0);
-
-// *** BELOW ARE INTERFACE VERSION 15 AND ABOVE ONLY
-// force any sprites on-screen using the slot to be updated
-AGSIFUNC(void)   NotifySpriteUpdated(int32 slot);
-// change whether the specified sprite is a 32-bit alpha blended image
-AGSIFUNC(void)   SetSpriteAlphaBlended(int32 slot, int32 isAlphaBlended);
-// run the specified script function whenever script engine is available
-AGSIFUNC(void)   QueueGameScriptFunction(const char *name, int32 globalScript, int32 numArgs, long arg1 = 0, long arg2 = 0);
-// register a new dynamic managed script object
-AGSIFUNC(int)    RegisterManagedObject(const void *object, IAGSScriptManagedObject *callback);
-// add an object reader for the specified object type
-AGSIFUNC(void)   AddManagedObjectReader(const char *typeName, IAGSManagedObjectReader *reader);
-// register an un-serialized managed script object
-AGSIFUNC(void)   RegisterUnserializedObject(int key, const void *object, IAGSScriptManagedObject *callback);
-
-// *** BELOW ARE INTERFACE VERSION 16 AND ABOVE ONLY
-// get the address of a managed object based on its key
-AGSIFUNC(void *)  GetManagedObjectAddressByKey(int key);
-// get managed object's key from its address
-AGSIFUNC(int)    GetManagedObjectKeyByAddress(const char *address);
-
-// *** BELOW ARE INTERFACE VERSION 17 AND ABOVE ONLY
-// create a new script string
-AGSIFUNC(const char *) CreateScriptString(const char *fromText);
-
-// *** BELOW ARE INTERFACE VERSION 18 AND ABOVE ONLY
-// increment reference count
-AGSIFUNC(int)    IncrementManagedObjectRefCount(const char *address);
-// decrement reference count
-AGSIFUNC(int)    DecrementManagedObjectRefCount(const char *address);
-// set mouse position
-AGSIFUNC(void)   SetMousePosition(int32 x, int32 y);
-// simulate the mouse being clicked
-AGSIFUNC(void)   SimulateMouseClick(int32 button);
-// get number of waypoints on this movement path
-AGSIFUNC(int)    GetMovementPathWaypointCount(int32 pathId);
-// get the last waypoint that the char/obj passed
-AGSIFUNC(int)    GetMovementPathLastWaypoint(int32 pathId);
-// get the co-ordinates of the specified waypoint
-AGSIFUNC(void)   GetMovementPathWaypointLocation(int32 pathId, int32 waypoint, int32 *x, int32 *y);
-// get the speeds of the specified waypoint
-AGSIFUNC(void)   GetMovementPathWaypointSpeed(int32 pathId, int32 waypoint, int32 *xSpeed, int32 *ySpeed);
-
-// *** BELOW ARE INTERFACE VERSION 19 AND ABOVE ONLY
-// get the current graphics driver ID
-AGSIFUNC(const char *) GetGraphicsDriverID();
-
-// *** BELOW ARE INTERFACE VERSION 22 AND ABOVE ONLY
-// get whether we are running under the editor's debugger
-AGSIFUNC(int)    IsRunningUnderDebugger();
-// tells the engine to break into the debugger when the next line of script is run
-AGSIFUNC(void)   BreakIntoDebugger();
-// fills buffer with <install dir>\fileName, as appropriate
-AGSIFUNC(void)   GetPathToFileInCompiledFolder(const char *fileName, char *buffer);
-
-// *** BELOW ARE INTERFACE VERSION 23 AND ABOVE ONLY
-#ifdef WINDOWS_VERSION
-// get reference to keyboard Direct Input device
-AGSIFUNC(LPDIRECTINPUTDEVICE) GetDirectInputKeyboard();
-// get reference to mouse Direct Input device
-AGSIFUNC(LPDIRECTINPUTDEVICE) GetDirectInputMouse();
-#endif
-// install a replacement renderer for the specified font number
-AGSIFUNC(IAGSFontRenderer *) ReplaceFontRenderer(int fontNumber, IAGSFontRenderer *newRenderer);
-
-// *** BELOW ARE INTERFACE VERSION 25 AND ABOVE ONLY
-// fills the provided AGSRenderStageDesc struct with current render stage description;
-// please note that plugin MUST fill the struct's Version field before passing it into the function!
-AGSIFUNC(void)  GetRenderStageDesc(AGSRenderStageDesc *desc);
+	virtual ~IAGSEngine() {}
+
+	// quit the game
+	AGSIFUNC(void) AbortGame(const char *reason);
+	// get engine version
+	AGSIFUNC(const char *) GetEngineVersion();
+	// register a script function with the system
+	AGSIFUNC(void) RegisterScriptFunction(const char *name, void *address);
+	#ifdef WINDOWS_VERSION
+	// get game window handle
+	AGSIFUNC(HWND) GetWindowHandle();
+	// get reference to main DirectDraw interface
+	AGSIFUNC(LPDIRECTDRAW2) GetDirectDraw2();
+	// get the DDraw surface associated with a bitmap
+	AGSIFUNC(LPDIRECTDRAWSURFACE2) GetBitmapSurface(BITMAP *);
+	#endif
+	// get a reference to the screen bitmap
+	AGSIFUNC(BITMAP *) GetScreen();
+
+	// *** BELOW ARE INTERFACE VERSION 2 AND ABOVE ONLY
+	// ask the engine to call back when a certain event happens
+	AGSIFUNC(void) RequestEventHook(int32 event);
+	// get the options data saved in the editor
+	AGSIFUNC(int)  GetSavedData(char *buffer, int32 bufsize);
+
+	// *** BELOW ARE INTERFACE VERSION 3 AND ABOVE ONLY
+	// get the virtual screen
+	AGSIFUNC(BITMAP *) GetVirtualScreen();
+	// write text to the screen in the specified font and colour
+	AGSIFUNC(void) DrawText(int32 x, int32 y, int32 font, int32 color, const char *text);
+	// get screen dimensions
+	AGSIFUNC(void) GetScreenDimensions(int32 *width, int32 *height, int32 *coldepth);
+	// get screen surface pitch
+	AGSIFUNC(int) GetBitmapPitch(BITMAP *);
+	// get screen surface to draw on
+	AGSIFUNC(uint8 *) GetRawBitmapSurface(BITMAP *);
+	// release the surface
+	AGSIFUNC(void) ReleaseBitmapSurface(BITMAP *);
+	// get the current mouse co-ordinates
+	AGSIFUNC(void) GetMousePosition(int32 *x, int32 *y);
+
+	// *** BELOW ARE INTERFACE VERSION 4 AND ABOVE ONLY
+	// get the current room number
+	AGSIFUNC(int)  GetCurrentRoom();
+	// get the number of background scenes in this room
+	AGSIFUNC(int)  GetNumBackgrounds();
+	// get the current background frame
+	AGSIFUNC(int)  GetCurrentBackground();
+	// get a background scene bitmap
+	AGSIFUNC(BITMAP *) GetBackgroundScene(int32);
+	// get dimensions of a bitmap
+	AGSIFUNC(void) GetBitmapDimensions(BITMAP *bmp, int32 *width, int32 *height, int32 *coldepth);
+
+	// *** BELOW ARE INTERFACE VERSION 5 AND ABOVE ONLY
+	// similar to fwrite - buffer, size, filehandle
+	AGSIFUNC(int)  FWrite(void *, int32, int32);
+	// similar to fread - buffer, size, filehandle
+	AGSIFUNC(int)  FRead(void *, int32, int32);
+	// print text, wrapping as usual
+	AGSIFUNC(void) DrawTextWrapped(int32 x, int32 y, int32 width, int32 font, int32 color, const char *text);
+	// set the current active 'screen'
+	AGSIFUNC(void) SetVirtualScreen(BITMAP *);
+	// look up a word in the parser dictionary
+	AGSIFUNC(int)  LookupParserWord(const char *word);
+	// draw a bitmap to the active screen
+	AGSIFUNC(void) BlitBitmap(int32 x, int32 y, BITMAP *, int32 masked);
+	// update the mouse and music
+	AGSIFUNC(void) PollSystem();
+
+	// *** BELOW ARE INTERFACE VERSION 6 AND ABOVE ONLY
+	// get number of characters in game
+	AGSIFUNC(int)  GetNumCharacters();
+	// get reference to specified character struct
+	AGSIFUNC(AGSCharacter *) GetCharacter(int32);
+	// get reference to game struct
+	AGSIFUNC(AGSGameOptions *) GetGameOptions();
+	// get reference to current palette
+	AGSIFUNC(AGSColor *) GetPalette();
+	// update palette
+	AGSIFUNC(void) SetPalette(int32 start, int32 finish, AGSColor *);
+
+	// *** BELOW ARE INTERFACE VERSION 7 AND ABOVE ONLY
+	// get the current player character
+	AGSIFUNC(int)  GetPlayerCharacter();
+	// adjust to main viewport co-ordinates
+	AGSIFUNC(void) RoomToViewport(int32 *x, int32 *y);
+	// adjust from main viewport co-ordinates (ignores viewport bounds)
+	AGSIFUNC(void) ViewportToRoom(int32 *x, int32 *y);
+	// number of objects in current room
+	AGSIFUNC(int)  GetNumObjects();
+	// get reference to specified object
+	AGSIFUNC(AGSObject *) GetObject(int32);
+	// get sprite graphic
+	AGSIFUNC(BITMAP *) GetSpriteGraphic(int32);
+	// create a new blank bitmap
+	AGSIFUNC(BITMAP *) CreateBlankBitmap(int32 width, int32 height, int32 coldep);
+	// free a created bitamp
+	AGSIFUNC(void) FreeBitmap(BITMAP *);
+
+	// *** BELOW ARE INTERFACE VERSION 8 AND ABOVE ONLY
+	// get one of the room area masks
+	AGSIFUNC(BITMAP *) GetRoomMask(int32);
+
+	// *** BELOW ARE INTERFACE VERSION 9 AND ABOVE ONLY
+	// get a particular view frame
+	AGSIFUNC(AGSViewFrame *) GetViewFrame(int32 view, int32 loop, int32 frame);
+	// get the walk-behind baseline of a specific WB area
+	AGSIFUNC(int)    GetWalkbehindBaseline(int32 walkbehind);
+	// get the address of a script function
+	AGSIFUNC(void *) GetScriptFunctionAddress(const char *funcName);
+	// get the transparent colour of a bitmap
+	AGSIFUNC(int)    GetBitmapTransparentColor(BITMAP *);
+	// get the character scaling level at a particular point
+	AGSIFUNC(int)    GetAreaScaling(int32 x, int32 y);
+	// equivalent to the text script function
+	AGSIFUNC(int)    IsGamePaused();
+
+	// *** BELOW ARE INTERFACE VERSION 10 AND ABOVE ONLY
+	// get the raw pixel value to use for the specified AGS colour
+	AGSIFUNC(int)    GetRawPixelColor(int32 color);
+
+	// *** BELOW ARE INTERFACE VERSION 11 AND ABOVE ONLY
+	// get the width / height of the specified sprite
+	AGSIFUNC(int)    GetSpriteWidth(int32);
+	AGSIFUNC(int)    GetSpriteHeight(int32);
+	// get the dimensions of the specified string in the specified font
+	AGSIFUNC(void)   GetTextExtent(int32 font, const char *text, int32 *width, int32 *height);
+	// print a message to the debug console
+	AGSIFUNC(void)   PrintDebugConsole(const char *text);
+	// play a sound on the specified channel
+	AGSIFUNC(void)   PlaySoundChannel(int32 channel, int32 soundType, int32 volume, int32 loop, const char *filename);
+	// same as text script function
+	AGSIFUNC(int)    IsChannelPlaying(int32 channel);
+
+	// *** BELOW ARE INTERFACE VERSION 12 AND ABOVE ONLY
+	// invalidate a region of the virtual screen
+	AGSIFUNC(void)   MarkRegionDirty(int32 left, int32 top, int32 right, int32 bottom);
+	// get mouse cursor details
+	AGSIFUNC(AGSMouseCursor *) GetMouseCursor(int32 cursor);
+	// get the various components of a pixel
+	AGSIFUNC(void)   GetRawColorComponents(int32 coldepth, int32 color, int32 *red, int32 *green, int32 *blue, int32 *alpha);
+	// make a pixel colour from the supplied components
+	AGSIFUNC(int)    MakeRawColorPixel(int32 coldepth, int32 red, int32 green, int32 blue, int32 alpha);
+	// get whether the font is TTF or SCI
+	AGSIFUNC(int)    GetFontType(int32 fontNum);
+	// create a new dynamic sprite slot
+	AGSIFUNC(int)    CreateDynamicSprite(int32 coldepth, int32 width, int32 height);
+	// free a created dynamic sprite
+	AGSIFUNC(void)   DeleteDynamicSprite(int32 slot);
+	// check if a sprite has an alpha channel
+	AGSIFUNC(int)    IsSpriteAlphaBlended(int32 slot);
+
+	// *** BELOW ARE INTERFACE VERSION 13 AND ABOVE ONLY
+	// un-request an event, requested earlier with RequestEventHook
+	AGSIFUNC(void)   UnrequestEventHook(int32 event);
+	// draw a translucent bitmap to the active screen
+	AGSIFUNC(void)   BlitSpriteTranslucent(int32 x, int32 y, BITMAP *, int32 trans);
+	// draw a sprite to the screen, but rotated around its centre
+	AGSIFUNC(void)   BlitSpriteRotated(int32 x, int32 y, BITMAP *, int32 angle);
+
+	// *** BELOW ARE INTERFACE VERSION 14 AND ABOVE ONLY
+	#ifdef WINDOWS_VERSION
+	// get reference to main DirectSound interface
+	AGSIFUNC(LPDIRECTSOUND) GetDirectSound();
+	#endif
+	// disable AGS sound engine
+	AGSIFUNC(void)   DisableSound();
+	// check whether a script function can be run now
+	AGSIFUNC(int)    CanRunScriptFunctionNow();
+	// call a user-defined script function
+	AGSIFUNC(int)    CallGameScriptFunction(const char *name, int32 globalScript, int32 numArgs, long arg1 = 0, long arg2 = 0, long arg3 = 0);
+
+	// *** BELOW ARE INTERFACE VERSION 15 AND ABOVE ONLY
+	// force any sprites on-screen using the slot to be updated
+	AGSIFUNC(void)   NotifySpriteUpdated(int32 slot);
+	// change whether the specified sprite is a 32-bit alpha blended image
+	AGSIFUNC(void)   SetSpriteAlphaBlended(int32 slot, int32 isAlphaBlended);
+	// run the specified script function whenever script engine is available
+	AGSIFUNC(void)   QueueGameScriptFunction(const char *name, int32 globalScript, int32 numArgs, long arg1 = 0, long arg2 = 0);
+	// register a new dynamic managed script object
+	AGSIFUNC(int)    RegisterManagedObject(const void *object, IAGSScriptManagedObject *callback);
+	// add an object reader for the specified object type
+	AGSIFUNC(void)   AddManagedObjectReader(const char *typeName, IAGSManagedObjectReader *reader);
+	// register an un-serialized managed script object
+	AGSIFUNC(void)   RegisterUnserializedObject(int key, const void *object, IAGSScriptManagedObject *callback);
+
+	// *** BELOW ARE INTERFACE VERSION 16 AND ABOVE ONLY
+	// get the address of a managed object based on its key
+	AGSIFUNC(void *)  GetManagedObjectAddressByKey(int key);
+	// get managed object's key from its address
+	AGSIFUNC(int)    GetManagedObjectKeyByAddress(const char *address);
+
+	// *** BELOW ARE INTERFACE VERSION 17 AND ABOVE ONLY
+	// create a new script string
+	AGSIFUNC(const char *) CreateScriptString(const char *fromText);
+
+	// *** BELOW ARE INTERFACE VERSION 18 AND ABOVE ONLY
+	// increment reference count
+	AGSIFUNC(int)    IncrementManagedObjectRefCount(const char *address);
+	// decrement reference count
+	AGSIFUNC(int)    DecrementManagedObjectRefCount(const char *address);
+	// set mouse position
+	AGSIFUNC(void)   SetMousePosition(int32 x, int32 y);
+	// simulate the mouse being clicked
+	AGSIFUNC(void)   SimulateMouseClick(int32 button);
+	// get number of waypoints on this movement path
+	AGSIFUNC(int)    GetMovementPathWaypointCount(int32 pathId);
+	// get the last waypoint that the char/obj passed
+	AGSIFUNC(int)    GetMovementPathLastWaypoint(int32 pathId);
+	// get the co-ordinates of the specified waypoint
+	AGSIFUNC(void)   GetMovementPathWaypointLocation(int32 pathId, int32 waypoint, int32 *x, int32 *y);
+	// get the speeds of the specified waypoint
+	AGSIFUNC(void)   GetMovementPathWaypointSpeed(int32 pathId, int32 waypoint, int32 *xSpeed, int32 *ySpeed);
+
+	// *** BELOW ARE INTERFACE VERSION 19 AND ABOVE ONLY
+	// get the current graphics driver ID
+	AGSIFUNC(const char *) GetGraphicsDriverID();
+
+	// *** BELOW ARE INTERFACE VERSION 22 AND ABOVE ONLY
+	// get whether we are running under the editor's debugger
+	AGSIFUNC(int)    IsRunningUnderDebugger();
+	// tells the engine to break into the debugger when the next line of script is run
+	AGSIFUNC(void)   BreakIntoDebugger();
+	// fills buffer with <install dir>\fileName, as appropriate
+	AGSIFUNC(void)   GetPathToFileInCompiledFolder(const char *fileName, char *buffer);
+
+	// *** BELOW ARE INTERFACE VERSION 23 AND ABOVE ONLY
+	#ifdef WINDOWS_VERSION
+	// get reference to keyboard Direct Input device
+	AGSIFUNC(LPDIRECTINPUTDEVICE) GetDirectInputKeyboard();
+	// get reference to mouse Direct Input device
+	AGSIFUNC(LPDIRECTINPUTDEVICE) GetDirectInputMouse();
+	#endif
+	// install a replacement renderer for the specified font number
+	AGSIFUNC(IAGSFontRenderer *) ReplaceFontRenderer(int fontNumber, IAGSFontRenderer *newRenderer);
+
+	// *** BELOW ARE INTERFACE VERSION 25 AND ABOVE ONLY
+	// fills the provided AGSRenderStageDesc struct with current render stage description;
+	// please note that plugin MUST fill the struct's Version field before passing it into the function!
+	AGSIFUNC(void)  GetRenderStageDesc(AGSRenderStageDesc *desc);
 };
 
 #ifdef THIS_IS_THE_PLUGIN


Commit: 4eb0c3bc2468bfabae11048f13ded4edb25b8040
    https://github.com/scummvm/scummvm/commit/4eb0c3bc2468bfabae11048f13ded4edb25b8040
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:52-07:00

Commit Message:
AGS: Graphical fixes

Changed paths:
    engines/ags/engine/ac/timer.cpp
    engines/ags/engine/gfx/ali_3d_scummvm.cpp
    engines/ags/engine/main/graphics_mode.cpp


diff --git a/engines/ags/engine/ac/timer.cpp b/engines/ags/engine/ac/timer.cpp
index 94e02567b5..6d263f04c6 100644
--- a/engines/ags/engine/ac/timer.cpp
+++ b/engines/ags/engine/ac/timer.cpp
@@ -73,8 +73,6 @@ void WaitForNextFrame() {
 	}
 
 	_G(next_frame_timestamp) += frameDuration;
-
-	::AGS::g_vm->_rawScreen->update();
 }
 
 void skipMissedTicks() {
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 50f609e9f2..f6c727b098 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -417,6 +417,8 @@ void ScummVMRendererGraphicsDriver::BlitToTexture() {
 void ScummVMRendererGraphicsDriver::Present() {
 	BlitToTexture();
 
+	::AGS::g_vm->_rawScreen->update();
+
 #if DEPRECATED
 	SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);
 	SDL_SetRenderDrawColor(_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
diff --git a/engines/ags/engine/main/graphics_mode.cpp b/engines/ags/engine/main/graphics_mode.cpp
index 7089c64bf0..769bf8725d 100644
--- a/engines/ags/engine/main/graphics_mode.cpp
+++ b/engines/ags/engine/main/graphics_mode.cpp
@@ -214,6 +214,9 @@ Size set_game_frame_after_screen_size(const Size &game_size, const Size screen_s
 }
 
 Size precalc_screen_size(const Size &game_size, const DisplayModeSetup &dm_setup, const GameFrameSetup &frame_setup) {
+#if AGS_PLATFORM_SCUMMVM
+	return game_size;
+#else
 	Size screen_size, frame_size;
 	Size device_size = get_max_display_size(dm_setup.Windowed);
 
@@ -246,6 +249,7 @@ Size precalc_screen_size(const Size &game_size, const DisplayModeSetup &dm_setup
 		break;
 	}
 	return screen_size;
+#endif
 }
 
 // Find closest possible compatible display mode and initialize it


Commit: 87dba2e27669c81c77c8c89e9906d42ac80d831e
    https://github.com/scummvm/scummvm/commit/87dba2e27669c81c77c8c89e9906d42ac80d831e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:52-07:00

Commit Message:
AGS: Re-added checks for SHOULD_QUIT and abort_engine

Changed paths:
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/sys_events.cpp
    engines/ags/engine/gui/csci_dialog.cpp
    engines/ags/engine/gui/gui_dialog.cpp
    engines/ags/engine/main/game_run.cpp
    engines/ags/engine/media/video/video.cpp
    engines/ags/engine/script/cc_instance.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/events.h


diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index a5354a2e7d..d952ff4112 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -64,6 +64,7 @@
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
 #include "ags/engine/ac/dynobj/script_string.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -84,6 +85,9 @@ int Dialog_DisplayOptions(ScriptDialog *sd, int sayChosenOption) {
 		quit("!Dialog.DisplayOptions: invalid parameter passed");
 
 	int chose = show_dialog_options(sd->id, sayChosenOption, (_GP(game).options[OPT_RUNGAMEDLGOPTS] != 0));
+	if (SHOULD_QUIT)
+		return -1;
+
 	if (chose != CHOSE_TEXTPARSER) {
 		chose++;
 	}
@@ -590,7 +594,7 @@ void DialogOptions::Show() {
 	update_polled_stuff_if_runtime();
 
 	Redraw();
-	while (Run());
+	while (Run() && !SHOULD_QUIT) {}
 
 	if (!_GP(play).mouse_cursor_hidden)
 		ags_domouse(DOMOUSE_DISABLE);
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index dda4726bfa..8ca8413b18 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -52,6 +52,7 @@
 #include "ags/engine/ac/mouse.h"
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/engine/ac/timer.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -258,6 +259,9 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 		int skip_setting = user_to_internal_skip_speech((SkipSpeechStyle)_GP(play).skip_display);
 		// Loop until skipped
 		while (true) {
+			if (SHOULD_QUIT)
+				return 0;
+
 			sys_evt_process_pending();
 
 			update_audio_system_on_game_loop();
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index ea8099c3a1..6b66ea894d 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -70,6 +70,7 @@
 #include "ags/engine/gfx/blender.h"
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/engine/ac/game.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -2237,7 +2238,7 @@ void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY
 	construct_game_screen_overlay(true);
 	render_to_screen();
 
-	if (!_GP(play).screen_is_faded_out) {
+	if (!SHOULD_QUIT && !_GP(play).screen_is_faded_out) {
 		// always update the _G(palette), regardless of whether the plugin
 		// vetos the screen update
 		if (_G(bg_just_changed)) {
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index 20fe42887c..f3f3ed5858 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -60,6 +60,8 @@ int run_claimable_event(const char *tsname, bool includeRoom, int numParams, con
 
 	if (includeRoom && _G(roominst)) {
 		toret = RunScriptFunctionIfExists(_G(roominst), tsname, numParams, params);
+		if (_G(abort_engine))
+			return -1;
 
 		if (_G(eventClaimed) == EVENT_CLAIMED) {
 			_G(eventClaimed) = eventClaimedOldValue;
@@ -178,6 +180,9 @@ void process_event(EventHappened *evp) {
 		} else
 			quit("process_event: RunEvBlock: unknown evb type");
 
+		if (_G(abort_engine))
+			return;
+
 		_G(evblockbasename) = oldbasename;
 		_G(evblocknum) = oldblocknum;
 
@@ -356,7 +361,7 @@ void processallevents(int numev, EventHappened *evlist) {
 
 		process_event(&copyOfList[dd]);
 
-		if (room_was != _GP(play).room_changes)
+		if (room_was != _GP(play).room_changes || _G(abort_engine))
 			break;  // changed room, so discard other events
 	}
 
@@ -367,6 +372,7 @@ void update_events() {
 	processallevents(_G(numevents), &_G(event)[0]);
 	_G(numevents) = 0;
 }
+
 // end event list functions
 
 
diff --git a/engines/ags/engine/ac/sys_events.cpp b/engines/ags/engine/ac/sys_events.cpp
index 03391710f3..a88f6fd1b3 100644
--- a/engines/ags/engine/ac/sys_events.cpp
+++ b/engines/ags/engine/ac/sys_events.cpp
@@ -32,6 +32,7 @@
 #include "ags/engine/device/mouse_w32.h"
 #include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/engine/main/engine.h"
+#include "ags/ags.h"
 #include "ags/events.h"
 #include "ags/globals.h"
 
@@ -133,10 +134,10 @@ static int sdl_button_to_mask(int button) {
 static int mouse_button_poll() {
 #ifdef TODO
 	auto now = AGS_Clock::now();
-	int result = mouse_button_state | mouse_accum_button_state;
-	if (now >= mouse_clear_at_time) {
-		mouse_accum_button_state = 0;
-		mouse_clear_at_time = now + std::chrono::milliseconds(50);
+	int result = _G(mouse_button_state) | _G(mouse_accum_button_state);
+	if (now >= _G(mouse_clear_at_time)) {
+		_G(mouse_accum_button_state) = 0;
+		_G(mouse_clear_at_time) = now + std::chrono::milliseconds(50);
 	}
 	return result;
 #else
@@ -157,10 +158,10 @@ static void on_sdl_mouse_button(const SDL_MouseButtonEvent &event) {
 	_G(sys_mouse_y) = _G(event).y;
 
 	if (_G(event).type == SDL_MOUSEBUTTONDOWN) {
-		mouse_button_state |= sdl_button_to_mask(_G(event).button);
-		mouse_accum_button_state |= sdl_button_to_mask(_G(event).button);
+		_G(mouse_button_state) |= sdl_button_to_mask(_G(event).button);
+		_G(mouse_accum_button_state) |= sdl_button_to_mask(_G(event).button);
 	} else {
-		mouse_button_state &= ~sdl_button_to_mask(_G(event).button);
+		_G(mouse_button_state) &= ~sdl_button_to_mask(_G(event).button);
 	}
 }
 
@@ -255,14 +256,12 @@ int ags_check_mouse_wheel() {
 
 
 void ags_clear_input_buffer() {
-#ifdef TODO
-	g_keyEvtQueue.clear();
-	mouse_button_state = 0;
-	mouse_accum_button_state = 0;
-	mouse_clear_at_time = AGS_Clock::now() + std::chrono::milliseconds(50);
+	::AGS::g_events->clearEvents();
 	_G(mouse_accum_relx) = 0;
 	_G(mouse_accum_rely) = 0;
-#endif
+	_G(mouse_button_state) = 0;
+	_G(mouse_accum_button_state) = 0;
+	_G(mouse_clear_at_time) = AGS_Clock::now() + std::chrono::milliseconds(50);
 }
 
 // TODO: this is an awful function that should be removed eventually.
@@ -271,7 +270,7 @@ void ags_wait_until_keypress() {
 	do {
 		sys_evt_process_pending();
 		_G(platform)->YieldCPU();
-	} while (!ags_keyevent_ready());
+	} while (!SHOULD_QUIT && !ags_keyevent_ready());
 	ags_clear_input_buffer();
 }
 
diff --git a/engines/ags/engine/gui/csci_dialog.cpp b/engines/ags/engine/gui/csci_dialog.cpp
index 16c083be9f..b8423e7f53 100644
--- a/engines/ags/engine/gui/csci_dialog.cpp
+++ b/engines/ags/engine/gui/csci_dialog.cpp
@@ -41,6 +41,7 @@
 #include "ags/engine/media/audio/audio_system.h"
 #include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/engine/ac/timer.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -125,7 +126,7 @@ int CSCIWaitMessage(CSCIMessage *cscim) {
 
 	prepare_gui_screen(_G(win_x), _G(win_y), _G(win_width), _G(win_height), true);
 
-	while (1) {
+	while (!SHOULD_QUIT) {
 		sys_evt_process_pending();
 
 		update_audio_system_on_game_loop();
diff --git a/engines/ags/engine/gui/gui_dialog.cpp b/engines/ags/engine/gui/gui_dialog.cpp
index af92b972a9..5d2d94e1bd 100644
--- a/engines/ags/engine/gui/gui_dialog.cpp
+++ b/engines/ags/engine/gui/gui_dialog.cpp
@@ -432,6 +432,9 @@ int myscimessagebox(const char *lpprompt, char *btn1, char *btn2) {
 	_GP(smes).code = 0;
 
 	do {
+		if (SHOULD_QUIT)
+			return 1;
+
 		CSCIWaitMessage(&_GP(smes));
 	} while (_GP(smes).code != CM_COMMAND);
 
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index ba55c08df4..61df73ec54 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -561,6 +561,10 @@ static void game_loop_check_controls(bool checkControls) {
 		int numevents_was = _G(numevents);
 		check_controls();
 		check_room_edges(numevents_was);
+
+		if (_G(abort_engine))
+			return;
+
 		// If an inventory interaction changed the room
 		if (inRoom != _G(displayed_room))
 			check_new_room();
@@ -628,7 +632,7 @@ static void game_loop_update_events() {
 		setevent(EV_FADEIN, 0, 0, 0);
 	_G(in_new_room) = 0;
 	update_events();
-	if ((_G(new_room_was) > 0) && (_G(in_new_room) == 0)) {
+	if (!_G(abort_engine) && (_G(new_room_was) > 0) && (_G(in_new_room) == 0)) {
 		// if in a new room, and the room wasn't just changed again in update_events,
 		// then queue the Enters Screen scripts
 		// run these next time round, when it's faded in
@@ -736,6 +740,9 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
 
 	game_loop_check_controls(checkControls);
 
+	if (_G(abort_engine))
+		return;
+
 	_G(our_eip) = 2;
 
 	game_loop_do_update();
@@ -752,6 +759,9 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
 
 	game_loop_update_events();
 
+	if (_G(abort_engine))
+		return;
+
 	_G(our_eip) = 7;
 
 	update_polled_stuff_if_runtime();
@@ -871,6 +881,10 @@ static int GameTick() {
 		quit("!A blocking function was called before the first room has been loaded");
 
 	UpdateGameOnce(true);
+
+	if (_G(abort_engine))
+		return -1;
+
 	UpdateMouseOverLocation();
 
 	_G(our_eip) = 76;
@@ -912,7 +926,7 @@ static void GameLoopUntilEvent(int untilwhat, const void *daaa) {
 	auto cached_user_disabled_for = _G(user_disabled_for);
 
 	SetupLoopParameters(untilwhat, daaa);
-	while (GameTick() == 0);
+	while (GameTick() == 0 && !_G(abort_engine)) {}
 
 	_G(our_eip) = 78;
 
diff --git a/engines/ags/engine/media/video/video.cpp b/engines/ags/engine/media/video/video.cpp
index 4da405b7e2..ac7fd318ce 100644
--- a/engines/ags/engine/media/video/video.cpp
+++ b/engines/ags/engine/media/video/video.cpp
@@ -82,7 +82,7 @@ static bool play_video(Video::VideoDecoder *decoder, const char *name, int skip,
 	}
 
 	update_polled_stuff_if_runtime();
-
+	 
 	decoder->start();
 	while (!SHOULD_QUIT && !decoder->endOfVideo()) {
 		if (decoder->needsUpdate()) {
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 1468518fe4..0af7ecb4a3 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -346,6 +346,9 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
 	pc = 0;
 	_G(current_instance) = currentInstanceWas;
 
+	if (_G(abort_engine))
+		return -1;
+
 	// NOTE that if proper multithreading is added this will need
 	// to be reconsidered, since the GC could be run in the middle
 	// of a RET from a function or something where there is an
@@ -420,6 +423,8 @@ int ccInstance::Run(int32_t curpc) {
 	FunctionCallStack func_callstack;
 
 	while (1) {
+		if (_G(abort_engine))
+			return -1;
 
 		/*
 		if (!codeInst->ReadOperation(codeOp, pc))
@@ -1014,7 +1019,7 @@ int ccInstance::Run(int32_t curpc) {
 				cc_error("invalid pointer type for function call: %d", reg1.Type);
 			}
 
-			if (_G(ccError)) {
+			if (_G(ccError) || _G(abort_engine)) {
 				return -1;
 			}
 
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 647c09cd29..7be60bcdc3 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -143,6 +143,9 @@ int run_interaction_event(Interaction *nint, int evnt, int chkAny, int isInv) {
 	// Right, so there were some commands defined in response to the event.
 	retval = run_interaction_commandlist(nint->Events[evnt].Response.get(), &nint->Events[evnt].TimesRun, &cmdsrun);
 
+	if (_G(abort_engine))
+		return -1;
+
 	// An inventory interaction, but the wrong item was used
 	if ((isInv) && (cmdsrun == 0))
 		run_unhandled_event(evnt);
@@ -358,6 +361,9 @@ int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, int numParam,
 	} else
 		quit("Too many parameters to RunScriptFunctionIfExists");
 
+	if (_G(abort_engine))
+		return -1;
+
 	// 100 is if Aborted (eg. because we are LoadAGSGame'ing)
 	if ((toret != 0) && (toret != -2) && (toret != 100)) {
 		quit_with_script_error(tsname);
@@ -429,7 +435,7 @@ int RunTextScript2IParam(ccInstance *sci, const char *tsname, const RuntimeScrip
 		bool eventWasClaimed;
 		int toret = run_claimable_event(tsname, true, 2, params, &eventWasClaimed);
 
-		if (eventWasClaimed)
+		if (eventWasClaimed || _G(abort_engine))
 			return toret;
 	}
 
@@ -827,6 +833,9 @@ int run_interaction_commandlist(InteractionCommandList *nicl, int *timesrun, int
 			break;
 		}
 
+		if (_G(abort_engine))
+			return -1;
+
 		// if the room changed within the action, nicl is no longer valid
 		if (room_was != _GP(play).room_changes)
 			return -1;
diff --git a/engines/ags/events.h b/engines/ags/events.h
index 3fdaae4d3e..db58c1fc44 100644
--- a/engines/ags/events.h
+++ b/engines/ags/events.h
@@ -97,6 +97,11 @@ public:
 	 */
 	bool isKeyPressed(AGS3::eAGSKeyCode key);
 
+	void clearEvents() {
+		_pendingEvents.clear();
+		_pendingKeys.clear();
+	}
+
 	/**
 	 * Returns the bitset of currently pressed modifier keys
 	 */


Commit: e4683025851fc2277f01f37757d86050cbe2a679
    https://github.com/scummvm/scummvm/commit/e4683025851fc2277f01f37757d86050cbe2a679
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:53-07:00

Commit Message:
AGS: Standardize the AGS String npos

Changed paths:
    engines/ags/engine/main/main.cpp
    engines/ags/shared/util/file_stream.cpp
    engines/ags/shared/util/string.cpp
    engines/ags/shared/util/string.h


diff --git a/engines/ags/engine/main/main.cpp b/engines/ags/engine/main/main.cpp
index 237dc49cbc..b4251a7cc0 100644
--- a/engines/ags/engine/main/main.cpp
+++ b/engines/ags/engine/main/main.cpp
@@ -286,7 +286,7 @@ int main_process_cmdline(ConfigTree &cfg, int argc, const char *argv[]) {
 		else if (ags_strnicmp(arg, "--log-", 6) == 0 && arg[6] != 0) {
 			String logarg = arg + 6;
 			size_t split_at = logarg.FindChar('=');
-			if (split_at >= 0)
+			if (split_at != String::npos)
 				cfg["log"][logarg.Left(split_at)] = logarg.Mid(split_at + 1);
 			else
 				cfg["log"][logarg] = "";
diff --git a/engines/ags/shared/util/file_stream.cpp b/engines/ags/shared/util/file_stream.cpp
index 974d74439d..50bbe7b497 100644
--- a/engines/ags/shared/util/file_stream.cpp
+++ b/engines/ags/shared/util/file_stream.cpp
@@ -191,6 +191,7 @@ void FileStream::Open(const String &file_name, FileOpenMode open_mode, FileWorkM
 		}
 
 	} else {
+
 		if (!file_name.CompareLeftNoCase(SAVE_FOLDER_PREFIX)) {
 			_outSave = g_system->getSavefileManager()->openForSaving(
 			               file_name + strlen(SAVE_FOLDER_PREFIX), false);
diff --git a/engines/ags/shared/util/string.cpp b/engines/ags/shared/util/string.cpp
index 7fb36065ec..5169f1ab6e 100644
--- a/engines/ags/shared/util/string.cpp
+++ b/engines/ags/shared/util/string.cpp
@@ -148,36 +148,36 @@ int String::CompareNoCase(const char *cstr) const {
 
 int String::CompareLeft(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
-	return strncmp(GetCStr(), cstr, count != (size_t)-1 ? count : strlen(cstr));
+	return strncmp(GetCStr(), cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareLeftNoCase(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
-	return ags_strnicmp(GetCStr(), cstr, count != (size_t)-1 ? count : strlen(cstr));
+	return ags_strnicmp(GetCStr(), cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareMid(const char *cstr, size_t from, size_t count) const {
 	cstr = cstr ? cstr : "";
 	from = Math::Min(from, GetLength());
-	return strncmp(GetCStr() + from, cstr, count != (size_t)-1 ? count : strlen(cstr));
+	return strncmp(GetCStr() + from, cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareMidNoCase(const char *cstr, size_t from, size_t count) const {
 	cstr = cstr ? cstr : "";
 	from = Math::Min(from, GetLength());
-	return ags_strnicmp(GetCStr() + from, cstr, count != (size_t)-1 ? count : strlen(cstr));
+	return ags_strnicmp(GetCStr() + from, cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareRight(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
-	count = count != (size_t)-1 ? count : strlen(cstr);
+	count = count != npos ? count : strlen(cstr);
 	size_t off = Math::Min(GetLength(), count);
 	return strncmp(GetCStr() + GetLength() - off, cstr, count);
 }
 
 int String::CompareRightNoCase(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
-	count = count != (size_t)-1 ? count : strlen(cstr);
+	count = count != npos ? count : strlen(cstr);
 	size_t off = Math::Min(GetLength(), count);
 	return ags_strnicmp(GetCStr() + GetLength() - off, cstr, count);
 }
@@ -187,12 +187,12 @@ size_t String::FindChar(char c, size_t from) const {
 		const char *found_cstr = strchr(_cstr + from, c);
 		return found_cstr ? found_cstr - _cstr : -1;
 	}
-	return (size_t)-1;
+	return npos;
 }
 
 size_t String::FindCharReverse(char c, size_t from) const {
 	if (!_cstr || !c) {
-		return (size_t)-1;
+		return npos;
 	}
 
 	from = Math::Min(from, _len - 1);
@@ -203,7 +203,7 @@ size_t String::FindCharReverse(char c, size_t from) const {
 		}
 		seek_ptr--;
 	}
-	return (size_t)-1;
+	return npos;
 }
 
 size_t String::FindString(const char *cstr, size_t from) const {
@@ -211,7 +211,7 @@ size_t String::FindString(const char *cstr, size_t from) const {
 		const char *found_cstr = strstr(_cstr + from, cstr);
 		return found_cstr ? found_cstr - _cstr : -1;
 	}
-	return (size_t)-1;
+	return npos;
 }
 
 bool String::FindSection(char separator, size_t first, size_t last, bool exclude_first_sep, bool exclude_last_sep,
@@ -226,10 +226,10 @@ bool String::FindSection(char separator, size_t first, size_t last, bool exclude
 	size_t this_field = 0;
 	size_t slice_from = 0;
 	size_t slice_to = _len;
-	size_t slice_at = (size_t)-1;
+	size_t slice_at = npos;
 	do {
 		slice_at = FindChar(separator, slice_at + 1);
-		if (slice_at == (size_t)-1)
+		if (slice_at == npos)
 			slice_at = _len;
 		// found where previous field ends
 		if (this_field == last) {
@@ -326,7 +326,7 @@ String String::Right(size_t count) const {
 String String::LeftSection(char separator, bool exclude_separator) const {
 	if (_cstr && separator) {
 		size_t slice_at = FindChar(separator);
-		if (slice_at != (size_t)-1) {
+		if (slice_at != npos) {
 			slice_at = exclude_separator ? slice_at : slice_at + 1;
 			return Left(slice_at);
 		}
@@ -337,7 +337,7 @@ String String::LeftSection(char separator, bool exclude_separator) const {
 String String::RightSection(char separator, bool exclude_separator) const {
 	if (_cstr && separator) {
 		size_t slice_at = FindCharReverse(separator);
-		if (slice_at != (size_t)-1) {
+		if (slice_at != npos) {
 			size_t count = exclude_separator ? _len - slice_at - 1 : _len - slice_at;
 			return Right(count);
 		}
@@ -460,7 +460,7 @@ void String::ClipRight(size_t count) {
 void String::ClipLeftSection(char separator, bool include_separator) {
 	if (_cstr && separator) {
 		size_t slice_at = FindChar(separator);
-		if (slice_at != (size_t)-1) {
+		if (slice_at != npos) {
 			ClipLeft(include_separator ? slice_at + 1 : slice_at);
 		} else
 			Empty();
@@ -470,7 +470,7 @@ void String::ClipLeftSection(char separator, bool include_separator) {
 void String::ClipRightSection(char separator, bool include_separator) {
 	if (_cstr && separator) {
 		size_t slice_at = FindCharReverse(separator);
-		if (slice_at != (size_t)-1) {
+		if (slice_at != npos) {
 			ClipRight(include_separator ? _len - slice_at : _len - slice_at - 1);
 		} else
 			Empty();
@@ -748,7 +748,7 @@ void String::TruncateToRight(size_t count) {
 void String::TruncateToLeftSection(char separator, bool exclude_separator) {
 	if (_cstr && separator) {
 		size_t slice_at = FindChar(separator);
-		if (slice_at != (size_t)-1) {
+		if (slice_at != npos) {
 			TruncateToLeft(exclude_separator ? slice_at : slice_at + 1);
 		}
 	}
@@ -757,7 +757,7 @@ void String::TruncateToLeftSection(char separator, bool exclude_separator) {
 void String::TruncateToRightSection(char separator, bool exclude_separator) {
 	if (_cstr && separator) {
 		size_t slice_at = FindCharReverse(separator);
-		if (slice_at != (size_t)-1) {
+		if (slice_at != npos) {
 			TruncateToRight(exclude_separator ? _len - slice_at - 1 : _len - slice_at);
 		}
 	}
diff --git a/engines/ags/shared/util/string.h b/engines/ags/shared/util/string.h
index 7af2d29aff..223857a88b 100644
--- a/engines/ags/shared/util/string.h
+++ b/engines/ags/shared/util/string.h
@@ -73,7 +73,7 @@ public:
 	String(const Common::String &s);
 	~String();
 
-	static const uint32 npos = 0xffffffff;
+	static const size_t npos = (size_t)-1;
 
 	// TODO: get rid of condition in GetCStr! either make it nullable and test for consequences in engine code,
 	// or make sure it points to "" literal when string is not assigned; also check if GetNullableCStr may be removed.


Commit: e73df29f6c344008aa79cf4840b7e2304cee6cf5
    https://github.com/scummvm/scummvm/commit/e73df29f6c344008aa79cf4840b7e2304cee6cf5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:53-07:00

Commit Message:
AGS: Engine fixes

Changed paths:
    engines/ags/engine/ac/sys_events.h
    engines/ags/engine/main/config.cpp
    engines/ags/globals.cpp
    engines/ags/shared/core/asset_manager.cpp


diff --git a/engines/ags/engine/ac/sys_events.h b/engines/ags/engine/ac/sys_events.h
index 4dcfe9639b..51afd18dc3 100644
--- a/engines/ags/engine/ac/sys_events.h
+++ b/engines/ags/engine/ac/sys_events.h
@@ -48,14 +48,6 @@ enum eAGSMouseButton {
 // avoid including SDL.h here, at least for now, because that leads to conflicts with allegro
 union SDL_Event;
 
-// Converts SDL key data to eAGSKeyCode, which may be also directly used as an ASCII char
-// if it is in proper range, see comments to eAGSKeyCode for details.
-eAGSKeyCode ags_keycode_from_sdl(const SDL_Event &event);
-// Converts eAGSKeyCode to SDL key scans (up to 3 values, because this is not a 1:1 match);
-// NOTE: fails at Ctrl+ or Alt+ AGS keys, or any unknown key codes.
-
-bool ags_key_to_sdl_scan(eAGSKeyCode key, Common::KeyState(&scan)[3]);
-
 // Tells if key event refers to one of the mod-keys
 inline bool is_mod_key(const Common::KeyState &ks) {
 	return ks.keycode == Common::KEYCODE_LCTRL || ks.keycode == Common::KEYCODE_RCTRL ||
diff --git a/engines/ags/engine/main/config.cpp b/engines/ags/engine/main/config.cpp
index bdcd1beadd..1be9e9323a 100644
--- a/engines/ags/engine/main/config.cpp
+++ b/engines/ags/engine/main/config.cpp
@@ -423,6 +423,8 @@ void post_config() {
 }
 
 void save_config_file() {
+	// ScummVM doesn't write out any configuration changes
+#if !AGS_PLATFORM_SCUMMVM
 	ConfigTree cfg;
 
 	// Last display mode
@@ -457,6 +459,7 @@ void save_config_file() {
 	String cfg_file = PreparePathForWriting(GetGameUserConfigDir(), DefaultConfigFileName);
 	if (!cfg_file.IsEmpty())
 		IniUtil::Merge(cfg_file, cfg);
+#endif
 }
 
 } // namespace AGS3
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index c49afe64d0..29de76c954 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -357,7 +357,7 @@ Globals::~Globals() {
 	// audio.cpp globals
 	delete _audioChannels;
 	delete _ambient;
-	delete _scrAudioChannel;
+	delete[] _scrAudioChannel;
 
 	// button.cpp globals
 	delete[] _animbuts;
@@ -513,7 +513,7 @@ Globals::~Globals() {
 	delete _rgb_table;
 
 	// route_finder_impl.cpp globals
-	delete _navpoints;
+	delete[] _navpoints;
 	delete _nav;
 
 	// screen.cpp globals
diff --git a/engines/ags/shared/core/asset_manager.cpp b/engines/ags/shared/core/asset_manager.cpp
index 0287a45ed2..0c56332780 100644
--- a/engines/ags/shared/core/asset_manager.cpp
+++ b/engines/ags/shared/core/asset_manager.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/memstream.h"
 #include "ags/lib/std/algorithm.h"
 #include "ags/lib/std/utility.h"
 #include "ags/shared/core/platform.h"
@@ -285,7 +286,13 @@ Common::SeekableReadStream *AssetManager::OpenAssetStream(const String &asset_na
 	if (!stream)
 		return nullptr;
 
-	return new ScummVMReadStream(stream);
+	// Get the contents of the asset
+	size_t dataSize = stream->GetLength();
+	byte *data = (byte *)malloc(dataSize);
+	stream->Read(data, dataSize);
+	delete stream;
+
+	return new Common::MemoryReadStream(data, dataSize, DisposeAfterUse::YES);
 }
 
 String GetAssetErrorText(AssetError err) {


Commit: 4b9b2aa95ad1df4b31eb03820fcd87e9d036e7f4
    https://github.com/scummvm/scummvm/commit/4b9b2aa95ad1df4b31eb03820fcd87e9d036e7f4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:54-07:00

Commit Message:
AGS: Fix mouse handling

Changed paths:
    engines/ags/engine/ac/sys_events.cpp


diff --git a/engines/ags/engine/ac/sys_events.cpp b/engines/ags/engine/ac/sys_events.cpp
index a88f6fd1b3..8d2aa2176b 100644
--- a/engines/ags/engine/ac/sys_events.cpp
+++ b/engines/ags/engine/ac/sys_events.cpp
@@ -90,49 +90,36 @@ void ags_simulate_keypress(eAGSKeyCode ags_key) {
 	::AGS::g_events->pushKeyboardEvent(e);
 }
 
+static void on_key_down(const Common::Event &event) {
 #ifdef TODO
-static void on_sdl_key_down(const Common::Event &event) {
 	// Engine is not structured very well yet, and we cannot pass this event where it's needed;
 	// instead we save it in the queue where it will be ready whenever any component asks for one.
 	g_keyEvtQueue.push_back(event);
-}
 #endif
-
-#ifdef TODO
-static void on_sdl_textinput(const Common::Event &event) {
-	// We also push text input events to the same queue, as this is only valid way to get proper
-	// text interpretation of the pressed key combination based on current system locale.
-	g_keyEvtQueue.push_back(event);
 }
-#endif
-
 
 // ----------------------------------------------------------------------------
 // MOUSE INPUT
 // ----------------------------------------------------------------------------
 
-#ifdef TODO
-static int sdl_button_to_mask(int button) {
-	switch (button) {
-	case SDL_BUTTON_LEFT:
+static int scummvm_button_to_mask(Common::EventType type) {
+	switch (type) {
+	case Common::EVENT_LBUTTONDOWN:
+	case Common::EVENT_LBUTTONUP:
 		return MouseBitLeft;
-	case SDL_BUTTON_RIGHT:
+	case Common::EVENT_RBUTTONDOWN:
+	case Common::EVENT_RBUTTONUP:
 		return MouseBitRight;
-	case SDL_BUTTON_MIDDLE:
+	case Common::EVENT_MBUTTONDOWN:
+	case Common::EVENT_MBUTTONUP:
 		return MouseBitMiddle;
-	case SDL_BUTTON_X1:
-		return MouseBitX1;
-	case SDL_BUTTON_X2:
-		return MouseBitX2;
+	default:
+		return 0;
 	}
-
-	return 0;
 }
-#endif
 
 // Returns accumulated mouse button state and clears internal cache by timer
 static int mouse_button_poll() {
-#ifdef TODO
 	auto now = AGS_Clock::now();
 	int result = _G(mouse_button_state) | _G(mouse_accum_button_state);
 	if (now >= _G(mouse_clear_at_time)) {
@@ -140,38 +127,37 @@ static int mouse_button_poll() {
 		_G(mouse_clear_at_time) = now + std::chrono::milliseconds(50);
 	}
 	return result;
-#else
-	return 0;
-#endif
 }
 
-#ifdef TODO
-static void on_sdl_mouse_motion(const SDL_MouseMotionEvent &event) {
-	_G(sys_mouse_x) = _G(event).x;
-	_G(sys_mouse_y) = _G(event).y;
-	_G(mouse_accum_relx) += _G(event).xrel;
-	_G(mouse_accum_rely) += _G(event).yrel;
+static void on_mouse_motion(const Common::Event &event) {
+	_G(sys_mouse_x) = event.mouse.x;
+	_G(sys_mouse_y) = event.mouse.y;
+	_G(mouse_accum_relx) += event.relMouse.x;
+	_G(mouse_accum_rely) += event.relMouse.y;
 }
 
-static void on_sdl_mouse_button(const SDL_MouseButtonEvent &event) {
-	_G(sys_mouse_x) = _G(event).x;
-	_G(sys_mouse_y) = _G(event).y;
+static void on_mouse_button(const Common::Event &event) {
+	_G(sys_mouse_x) = event.mouse.x;
+	_G(sys_mouse_y) = event.mouse.y;
 
-	if (_G(event).type == SDL_MOUSEBUTTONDOWN) {
-		_G(mouse_button_state) |= sdl_button_to_mask(_G(event).button);
-		_G(mouse_accum_button_state) |= sdl_button_to_mask(_G(event).button);
+	if (event.type == Common::EVENT_LBUTTONDOWN ||
+			event.type == Common::EVENT_RBUTTONDOWN ||
+			event.type == Common::EVENT_MBUTTONDOWN) {
+		_G(mouse_button_state) |= scummvm_button_to_mask(event.type);
+		_G(mouse_accum_button_state) |= scummvm_button_to_mask(event.type);
 	} else {
-		_G(mouse_button_state) &= ~sdl_button_to_mask(_G(event).button);
+		_G(mouse_button_state) &= ~scummvm_button_to_mask(event.type);
 	}
 }
 
-static void on_sdl_mouse_wheel(const SDL_MouseWheelEvent &event) {
-	_G(sys_mouse_z) += _G(event).y;
+static void on_mouse_wheel(const Common::Event &event) {
+	if (event.type == Common::EVENT_WHEELDOWN)
+		_G(sys_mouse_z)++;
+	else
+		_G(sys_mouse_z)--;
 }
-#endif
 
 int mgetbutton() {
-#ifdef TODO
 	int toret = MouseNone;
 	int butis = mouse_button_poll();
 
@@ -197,7 +183,6 @@ int mgetbutton() {
 	if (ags_iskeypressed(__allegro_KEY_LCONTROL) || ags_iskeypressed(__allegro_KEY_RCONTROL)) {
 		toret = RIGHT;
 	}
-#endif
 #endif
 	return 0;
 }
@@ -207,7 +192,6 @@ bool ags_misbuttondown(int but) {
 }
 
 int ags_mgetbutton() {
-#ifdef TODO
 	int result;
 
 	if (_G(pluginSimulatedClick) > MouseNone) {
@@ -217,8 +201,6 @@ int ags_mgetbutton() {
 		result = mgetbutton();
 	}
 	return result;
-#endif
-	return 0;
 }
 
 void ags_mouse_get_relxy(int &x, int &y) {
@@ -288,61 +270,40 @@ void sys_evt_set_focus_callbacks(void(*switch_in)(void), void(*switch_out)(void)
 	_on_switchout_callback = switch_out;
 }
 
-#ifdef TODO
-void sys_evt_process_one(const Common::Event &event) {
-	switch (_G(event).type) {
-	// GENERAL
-	case SDL_QUIT:
-		if (_on_quit_callback) {
-			_on_quit_callback();
-		}
-		break;
-	// WINDOW
-	case SDL_WINDOWEVENT:
-		switch (_G(event).window.event) {
-		case SDL_WINDOWEVENT_FOCUS_GAINED:
-			if (_on_switchin_callback) {
-				_on_switchin_callback();
-			}
-			break;
-		case SDL_WINDOWEVENT_FOCUS_LOST:
-			if (_on_switchout_callback) {
-				_on_switchout_callback();
-			}
-			break;
-		case SDL_WINDOWEVENT_SIZE_CHANGED:
-			engine_on_window_changed(Size(_G(event).window.data1, _G(event).window.data2));
-			break;
-		}
+static void sys_process_event(const Common::Event &event) {
+	switch (event.type) {
+	case Common::EVENT_KEYDOWN:
+		on_key_down(event);
 		break;
-	// INPUT
-	case SDL_KEYDOWN:
-		on_sdl_key_down(event);
+	case Common::EVENT_MOUSEMOVE:
+		on_mouse_motion(event);
 		break;
-	case SDL_TEXTINPUT:
-		on_sdl_textinput(event);
+	case Common::EVENT_LBUTTONDOWN:
+	case Common::EVENT_RBUTTONDOWN:
+	case Common::EVENT_MBUTTONDOWN:
+	case Common::EVENT_LBUTTONUP:
+	case Common::EVENT_RBUTTONUP:
+	case Common::EVENT_MBUTTONUP:
+		on_mouse_button(event);
 		break;
-	case SDL_MOUSEMOTION:
-		on_sdl_mouse_motion(_G(event).motion);
+	case Common::EVENT_WHEELDOWN:
+	case Common::EVENT_WHEELUP:
+		on_mouse_wheel(event);
 		break;
-	case SDL_MOUSEBUTTONDOWN:
-	case SDL_MOUSEBUTTONUP:
-		on_sdl_mouse_button(_G(event).button);
-		break;
-	case SDL_MOUSEWHEEL:
-		on_sdl_mouse_wheel(_G(event).wheel);
+	default:
 		break;
 	}
 }
-#endif
 
 void sys_evt_process_pending(void) {
-#ifdef TODO
-	Common::Event event;
-	while (SDL_PollEvent(&event)) {
-		sys_evt_process_one(event);
-	}
-#endif
+	::AGS::g_events->pollEvents();
+	Common::Event e;
+
+	while ((e = ::AGS::g_events->readEvent()).type != Common::EVENT_INVALID)
+		sys_process_event(e);
+
+	while ((e = ::AGS::g_events->readEvent()).type != Common::EVENT_INVALID)
+		sys_process_event(e);
 }
 
 } // namespace AGS3


Commit: 7cb1094a60851bf5048533fc967870b250dceacf
    https://github.com/scummvm/scummvm/commit/7cb1094a60851bf5048533fc967870b250dceacf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:54-07:00

Commit Message:
AGS: Re-enable savegame code

Changed paths:
    engines/ags/engine/ac/file.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/game/main_game_file.h
    engines/ags/shared/util/file.cpp


diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index cab74dad94..af7969bcac 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/config-manager.h"
 #include "ags/engine/ac/asset_helper.h"
 #include "ags/shared/ac/audio_clip_type.h"
 #include "ags/engine/ac/file.h"
@@ -48,6 +49,7 @@
 #include "ags/engine/script/script_api.h"
 #include "ags/engine/script/script_runtime.h"
 #include "ags/engine/ac/dynobj/script_string.h"
+#include "ags/ags.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -302,18 +304,10 @@ FSLocation GetGameUserDataDir() {
 }
 
 bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath &rp) {
+	debugC(::AGS::kDebugFilePath, "ResolveScriptPath(%s)", orig_sc_path.GetCStr());
 	rp = ResolvedPath();
 
-	// File tokens (they must be the only thing in script path)
-	if (orig_sc_path.Compare(UserConfigFileToken) == 0) {
-		auto loc = GetGameUserConfigDir();
-		rp.FullPath = Path::ConcatPaths(loc.FullDir, DefaultConfigFileName);
-		rp.BaseDir = loc.BaseDir;
-		return true;
-	}
-
-	// Test absolute paths
-	bool is_absolute = !Path::IsRelativePath(orig_sc_path);
+	bool is_absolute = !is_relative_filename(orig_sc_path);
 	if (is_absolute && !read_only) {
 		debug_script_warn("Attempt to access file '%s' denied (cannot write to absolute path)", orig_sc_path.GetCStr());
 		return false;
@@ -321,55 +315,91 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 
 	if (is_absolute) {
 		rp.FullPath = orig_sc_path;
+		debugC(::AGS::kDebugFilePath, "Full path detected");
 		return true;
 	}
-
-	// Resolve location tokens
+	/*
+	if (read_only) {
+		// For reading files, first try as a save file, then fall back
+		// in the game folder. This handles cases where some games like
+		// The Blackwell Legacy write to files in the game folder
+		rp.BaseDir = SAVE_FOLDER_PREFIX;
+		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
+			orig_sc_path.GetNullableCStr());
+		rp.AltPath = orig_sc_path;
+	} else {
+		// For writing files, always use as save files
+		rp.BaseDir = SAVE_FOLDER_PREFIX;
+		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
+			orig_sc_path.GetNullableCStr());
+	}
+	*/
 	String sc_path = FixSlashAfterToken(orig_sc_path);
 	FSLocation parent_dir;
 	String child_path;
 	String alt_path;
-	if (sc_path.CompareLeft(GameInstallRootToken, GameInstallRootToken.GetLength()) == 0) {
+	if (sc_path.CompareLeft(GameInstallRootToken) == 0) {
 		if (!read_only) {
 			debug_script_warn("Attempt to access file '%s' denied (cannot write to game installation directory)",
-			                  sc_path.GetCStr());
+				sc_path.GetCStr());
 			return false;
 		}
 		parent_dir = FSLocation(_GP(ResPaths).DataDir);
 		child_path = sc_path.Mid(GameInstallRootToken.GetLength());
-	} else if (sc_path.CompareLeft(GameSavedgamesDirToken, GameSavedgamesDirToken.GetLength()) == 0) {
-		parent_dir = FSLocation(get_save_game_directory()); // FIXME: get FSLocation of save dir
-		child_path = sc_path.Mid(GameSavedgamesDirToken.GetLength());
-	} else if (sc_path.CompareLeft(GameDataDirToken, GameDataDirToken.GetLength()) == 0) {
+	} else if (sc_path.CompareLeft(GameSavedgamesDirToken) == 0) {
+		parent_dir = get_save_game_directory();
+		child_path = sc_path.Mid(strlen(GameSavedgamesDirToken));
+#if AGS_PLATFORM_SCUMMVM
+		// Remap "agsgame.*"
+		const char *agsSavePrefix = "/agssave.";
+		if (child_path.CompareLeft(agsSavePrefix) == 0) {
+			debugC(::AGS::kDebugFilePath, "Remapping agssave.* to ScummVM savegame files");
+			String suffix = child_path.Mid(strlen(agsSavePrefix));
+			if (suffix.CompareLeft("*") == 0) {
+				Common::String file_name = ::AGS::g_vm->getSaveStateName(999);
+				Common::replace(file_name, "999", "*");
+				child_path = file_name;
+			} else {
+				int slotNum = suffix.ToInt();
+				child_path = ::AGS::g_vm->getSaveStateName(slotNum);
+			}
+		}
+#endif
+	} else if (sc_path.CompareLeft(GameDataDirToken) == 0) {
 		parent_dir = GetGameAppDataDir();
 		child_path = sc_path.Mid(GameDataDirToken.GetLength());
 	} else {
 		child_path = sc_path;
 
-		// For games which were made without having safe paths in mind,
-		// provide two paths: a path to the local directory and a path to
-		// AppData directory.
-		// This is done in case game writes a file by local path, and would
-		// like to read it back later. Since AppData path has higher priority,
-		// game will first check the AppData location and find a previously
-		// written file.
-		// If no file was written yet, but game is trying to read a pre-created
-		// file in the installation directory, then such file will be found
-		// following the 'alt_path'.
-		parent_dir = GetGameAppDataDir();
-		// Set alternate non-remapped "unsafe" path for read-only operations
-		if (read_only)
-			alt_path = Path::ConcatPaths(_GP(ResPaths).DataDir, sc_path);
-
-		// For games made in the safe-path-aware versions of AGS, report a warning
-		// if the unsafe path is used for write operation
-		if (!read_only && _GP(game).options[OPT_SAFEFILEPATHS]) {
-			debug_script_warn("Attempt to access file '%s' denied (cannot write to game installation directory);\nPath will be remapped to the app data directory: '%s'",
-			                  sc_path.GetCStr(), parent_dir.FullDir.GetCStr());
+		// For cases where a file is trying to write to a game path, always remap
+		// it to write to a savefile. For normal reading, we thus need to give
+		// preference to any save file with a given name before looking in the
+		// game folder. This for example fixes an issue with The Blackwell Legacy,
+		// which wants to create a new prog.bwl in the game folder
+		parent_dir = FSLocation(SAVE_FOLDER_PREFIX);
+
+		if (read_only) {
+			alt_path = sc_path;
 		}
 	}
 
-	String full_path = Path::ConcatPaths(parent_dir.FullDir, child_path);
+	// Sometimes we have multiple consecutive slashes or backslashes.
+	// Remove all of them at the start of the child path.
+	while (!child_path.IsEmpty() && (child_path[0u] == '\\' || child_path[0u] == '/'))
+		child_path.ClipLeft(1);
+
+#if AGS_PLATFORM_SCUMMVM
+	// For files on savepath, always ensure it starts with the game target prefix to avoid
+	// conflicts (as we usually have the same save dir for all games).
+	if (parent_dir.BaseDir == SAVE_FOLDER_PREFIX) {
+		debugC(::AGS::kDebugFilePath, "Adding ScummVM game target prefix");
+		String gameTarget = ConfMan.getActiveDomainName();
+		if (child_path.CompareLeft(gameTarget) != 0)
+			child_path = String::FromFormat("%s-%s", gameTarget.GetCStr(), child_path.GetCStr());
+	}
+#endif
+
+	String full_path = String::FromFormat("%s%s", parent_dir.BaseDir.GetCStr(), child_path.GetCStr());
 	// don't allow write operations for relative paths outside game dir
 	if (!read_only) {
 		if (!Path::IsSameOrSubDir(parent_dir.FullDir, full_path)) {
@@ -377,9 +407,15 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 			return false;
 		}
 	}
+
 	rp.BaseDir = parent_dir.BaseDir;
 	rp.FullPath = full_path;
 	rp.AltPath = alt_path;
+
+	debugC(::AGS::kDebugFilePath, "Resolved path: %s", full_path.GetCStr());
+	if (!alt_path.IsEmpty())
+		debugC(::AGS::kDebugFilePath, "Alternative path: %s", alt_path.GetCStr());
+
 	return true;
 }
 
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 52ea5118c4..1eda29cf6b 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -222,9 +222,11 @@ void set_save_game_suffix(const String &suffix) {
 	_G(saveGameSuffix) = suffix;
 }
 
+#if !AGS_PLATFORM_SCUMMVM
 String get_save_game_filename(int slotNum) {
 	return String::FromFormat("agssave.%03d%s", slotNum, _G(saveGameSuffix).GetCStr());
 }
+#endif
 
 String get_save_game_path(int slotNum) {
 #if AGS_PLATFORM_SCUMMVM
@@ -930,9 +932,6 @@ void save_game(int slotn, const char *descript) {
 	}
 }
 
-int gameHasBeenRestored = 0;
-int oldeip;
-
 bool read_savedgame_description(const String &savedgame, String &description) {
 	SavegameDescription desc;
 	HSaveError err = OpenSavegame(savedgame, desc, kSvgDesc_UserText);
@@ -979,12 +978,16 @@ bool test_game_guid(const String &filepath, const String &guid, int legacy_id) {
 	return legacy_id == g.uniqueid;
 }
 
+static const SavegameDescription *loadDesc;
+static bool TestGame(const String &filepath) {
+	return test_game_guid(filepath, loadDesc->GameGuid, loadDesc->LegacyID);
+}
+
 HSaveError load_game(const String &path, int slotNumber, bool &data_overwritten) {
-#ifdef TODO
 	data_overwritten = false;
-	gameHasBeenRestored++;
+	_G(gameHasBeenRestored)++;
 
-	oldeip = _G(our_eip);
+	_G(oldeip) = _G(our_eip);
 	_G(our_eip) = 2050;
 
 	HSaveError err;
@@ -1004,10 +1007,9 @@ HSaveError load_game(const String &path, int slotNumber, bool &data_overwritten)
 	if (!desc.GameGuid.IsEmpty() || desc.LegacyID != 0) {
 		if (desc.GameGuid.Compare(_GP(game).guid) != 0 && desc.LegacyID != _GP(game).uniqueid) {
 			// Try to find wanted game's data using game id
-			String gamefile = FindGameData(_GP(ResPaths).DataDir,
-			[&desc](const String & filepath) {
-				return test_game_guid(filepath, desc.GameGuid, desc.LegacyID);
-			});
+			loadDesc = &desc;
+			String gamefile = FindGameData(_GP(ResPaths).DataDir, TestGame);
+
 			if (Shared::File::TestReadFile(gamefile)) {
 				RunAGSGame(desc.MainDataFilename, 0, 0);
 				_G(load_new_game_restore) = slotNumber;
@@ -1036,16 +1038,13 @@ HSaveError load_game(const String &path, int slotNumber, bool &data_overwritten)
 	if (!err)
 		return err;
 	src.InputStream.reset();
-	_G(our_eip) = oldeip;
+	_G(our_eip) = _G(oldeip);
 
 	// ensure keyboard buffer is clean
 	ags_clear_input_buffer();
 	// call "After Restore" event callback
 	run_on_event(GE_RESTORE_GAME, RuntimeScriptValue().SetInt32(slotNumber));
 	return HSaveError::None();
-#else
-	error("TODO: load_game");
-#endif
 }
 
 bool try_restore_save(int slot) {
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 375c3eb8ff..c8935dde28 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -131,7 +131,7 @@ bool IsMainGameLibrary(const String &filename) {
 // - ac2game.dat is a legacy file name for very old games,
 // - *.exe is a MS Win executable; it is included to this case because
 //   users often run AGS ports with Windows versions of games.
-String FindGameData(const String &path, std::function<bool(const String &)> fn_testfile) {
+String FindGameData(const String &path, bool(*fn_testfile)(const String &)) {
 	Common::FSNode folder(path.GetCStr());
 	Common::FSList files;
 	if (folder.getChildren(files, Common::FSNode::kListFilesOnly)) {
diff --git a/engines/ags/shared/game/main_game_file.h b/engines/ags/shared/game/main_game_file.h
index 00f614be67..69643b7023 100644
--- a/engines/ags/shared/game/main_game_file.h
+++ b/engines/ags/shared/game/main_game_file.h
@@ -147,7 +147,7 @@ struct LoadedGameEntities {
 bool               IsMainGameLibrary(const String &filename);
 // Scans given directory path for a package containing main game data, returns first found or none.
 String             FindGameData(const String &path);
-String             FindGameData(const String &path, std::function<bool(const String &)> fn_testfile);
+String             FindGameData(const String &path, bool(*fn_testfile)(const String &));
 // Opens main game file for reading from an arbitrary file
 HGameFileError     OpenMainGameFile(const String &filename, MainGameSource &src);
 // Opens main game file for reading from the asset library (uses default asset name)
diff --git a/engines/ags/shared/util/file.cpp b/engines/ags/shared/util/file.cpp
index 6f3c3277b6..9da30ad869 100644
--- a/engines/ags/shared/util/file.cpp
+++ b/engines/ags/shared/util/file.cpp
@@ -55,9 +55,11 @@ bool File::TestWriteFile(const String &filename) {
 bool File::TestCreateFile(const String &filename) {
 	if (filename.IsEmpty())
 		return false;
-	Common::DumpFile df;
-	bool result = df.open(getFSNode(filename.GetNullableCStr()));
-	df.close();
+
+	Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(filename);
+	bool result = sf != nullptr;
+	delete sf;
+
 	return result;
 }
 


Commit: 98a923425361945e0452bec280c8defb021e3d83
    https://github.com/scummvm/scummvm/commit/98a923425361945e0452bec280c8defb021e3d83
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:54-07:00

Commit Message:
AGS: Hooked in keyboard handling

Changed paths:
  R engines/ags/lib/allegro/keyboard.cpp
  R engines/ags/lib/allegro/keyboard.h
    engines/ags/engine/ac/sys_events.cpp
    engines/ags/engine/ac/sys_events.h
    engines/ags/engine/ac/system.cpp
    engines/ags/events.cpp
    engines/ags/events.h
    engines/ags/lib/allegro.h
    engines/ags/module.mk
    engines/ags/plugins/ags_creditz/ags_creditz1.cpp


diff --git a/engines/ags/engine/ac/sys_events.cpp b/engines/ags/engine/ac/sys_events.cpp
index 8d2aa2176b..6ccf1c927f 100644
--- a/engines/ags/engine/ac/sys_events.cpp
+++ b/engines/ags/engine/ac/sys_events.cpp
@@ -65,11 +65,11 @@ static void(*_on_switchout_callback)(void) = nullptr;
 // ----------------------------------------------------------------------------
 
 bool ags_keyevent_ready() {
-	return ::AGS::g_events->keypressed();
+	return ::AGS::g_events->keyEventPending();
 }
 
 Common::Event ags_get_next_keyevent() {
-	return ::AGS::g_events->readKey();
+	return ::AGS::g_events->getPendingKeyEvent();
 }
 
 int ags_iskeydown(eAGSKeyCode ags_key) {
@@ -90,14 +90,6 @@ void ags_simulate_keypress(eAGSKeyCode ags_key) {
 	::AGS::g_events->pushKeyboardEvent(e);
 }
 
-static void on_key_down(const Common::Event &event) {
-#ifdef TODO
-	// Engine is not structured very well yet, and we cannot pass this event where it's needed;
-	// instead we save it in the queue where it will be ready whenever any component asks for one.
-	g_keyEvtQueue.push_back(event);
-#endif
-}
-
 // ----------------------------------------------------------------------------
 // MOUSE INPUT
 // ----------------------------------------------------------------------------
@@ -272,9 +264,6 @@ void sys_evt_set_focus_callbacks(void(*switch_in)(void), void(*switch_out)(void)
 
 static void sys_process_event(const Common::Event &event) {
 	switch (event.type) {
-	case Common::EVENT_KEYDOWN:
-		on_key_down(event);
-		break;
 	case Common::EVENT_MOUSEMOVE:
 		on_mouse_motion(event);
 		break;
@@ -301,9 +290,6 @@ void sys_evt_process_pending(void) {
 
 	while ((e = ::AGS::g_events->readEvent()).type != Common::EVENT_INVALID)
 		sys_process_event(e);
-
-	while ((e = ::AGS::g_events->readEvent()).type != Common::EVENT_INVALID)
-		sys_process_event(e);
 }
 
 } // namespace AGS3
diff --git a/engines/ags/engine/ac/sys_events.h b/engines/ags/engine/ac/sys_events.h
index 51afd18dc3..e11ae305ad 100644
--- a/engines/ags/engine/ac/sys_events.h
+++ b/engines/ags/engine/ac/sys_events.h
@@ -66,53 +66,56 @@ inline int make_merged_mod(int mod) {
 	return m_mod;
 }
 
+extern eAGSKeyCode ags_keycode_from_ScummVM(const Common::Event &event);
+extern bool ags_key_to_scummvm_keycode(eAGSKeyCode key, Common::KeyCode(&scan)[3]);
+
 // Tells if there are any buffered key events
-bool ags_keyevent_ready();
+extern bool ags_keyevent_ready();
 // Queries for the next key event in buffer; returns uninitialized data if none was queued
-Common::Event ags_get_next_keyevent();
+extern Common::Event ags_get_next_keyevent();
 // Tells if the key is currently down, provided AGS key;
 // Returns positive value if it's down, 0 if it's not, negative value if the key code is not supported.
 // NOTE: for particular script codes this function returns positive if either of two keys are down.
-int ags_iskeydown(eAGSKeyCode ags_key);
+extern int ags_iskeydown(eAGSKeyCode ags_key);
 // Simulates key press with the given AGS key
-void ags_simulate_keypress(eAGSKeyCode ags_key);
+extern void ags_simulate_keypress(eAGSKeyCode ags_key);
 
 
 // Mouse input handling
 //
 // Tells if the mouse button is currently down
-bool ags_misbuttondown(int but);
+extern bool ags_misbuttondown(int but);
 // Returns mouse button code
-int  ags_mgetbutton();
+extern int  ags_mgetbutton();
 // Returns recent relative mouse movement
-void ags_mouse_get_relxy(int &x, int &y);
+extern void ags_mouse_get_relxy(int &x, int &y);
 // Updates mouse cursor position in game
-void ags_domouse(int what);
+extern void ags_domouse(int what);
 // Returns -1 for wheel down and +1 for wheel up
 // TODO: introduce constants for this
-int  ags_check_mouse_wheel();
+extern int  ags_check_mouse_wheel();
 
 // Other input utilities
 //
 // Clears buffered keypresses and mouse clicks, if any
-void ags_clear_input_buffer();
+extern void ags_clear_input_buffer();
 // Halts execution until any user input
 // TODO: seriously not a good design, replace with event listening
-void ags_wait_until_keypress();
+extern void ags_wait_until_keypress();
 
 
 // Events.
 //
-union SDL_Event;
+
 // Set engine callback for when quit event is received by the backend.
-void sys_evt_set_quit_callback(void(*proc)(void));
+extern void sys_evt_set_quit_callback(void(*proc)(void));
 // Set engine callback for when input focus is received or lost by the window.
-void sys_evt_set_focus_callbacks(void(*switch_in)(void), void(*switch_out)(void));
+extern void sys_evt_set_focus_callbacks(void(*switch_in)(void), void(*switch_out)(void));
 
 // Process single event.
-void sys_evt_process_one(const SDL_Event &event);
+//extern void sys_evt_process_one(const Common::Event &event);
 // Process all events in the backend's queue.
-void sys_evt_process_pending(void);
+extern void sys_evt_process_pending(void);
 
 } // namespace AGS3
 
diff --git a/engines/ags/engine/ac/system.cpp b/engines/ags/engine/ac/system.cpp
index 93b18616e1..15d3e5df5c 100644
--- a/engines/ags/engine/ac/system.cpp
+++ b/engines/ags/engine/ac/system.cpp
@@ -106,15 +106,15 @@ int System_GetHardwareAcceleration() {
 }
 
 int System_GetNumLock() {
-	return (::AGS::g_events->getModifierFlags() & __allegro_KB_NUMLOCK_FLAG) ? 1 : 0;
+	return (::AGS::g_events->getModifierFlags() & Common::KBD_NUM) ? 1 : 0;
 }
 
 int System_GetCapsLock() {
-	return (::AGS::g_events->getModifierFlags() & __allegro_KB_CAPSLOCK_FLAG) ? 1 : 0;
+	return (::AGS::g_events->getModifierFlags() & Common::KBD_CAPS) ? 1 : 0;
 }
 
 int System_GetScrollLock() {
-	return (::AGS::g_events->getModifierFlags() & __allegro_KB_SCROLOCK_FLAG) ? 1 : 0;
+	return (::AGS::g_events->getModifierFlags() & Common::KBD_SCRL) ? 1 : 0;
 }
 
 int System_GetVsync() {
diff --git a/engines/ags/events.cpp b/engines/ags/events.cpp
index 6ca141df24..f6ec16326f 100644
--- a/engines/ags/events.cpp
+++ b/engines/ags/events.cpp
@@ -30,7 +30,7 @@ EventsManager *g_events;
 
 EventsManager::EventsManager() {
 	g_events = this;
-	_keys.resize(AGS3::__allegro_KEY_MAX);
+	_keys.resize(Common::KEYCODE_LAST);
 	Common::fill(&_joystickAxis[0], &_joystickAxis[32], 0);
 	Common::fill(&_joystickButton[0], &_joystickButton[32], 0);
 }
@@ -68,12 +68,11 @@ void EventsManager::pollEvents() {
 
 		case Common::EVENT_KEYDOWN:
 			updateKeys(e, true);
-			_pendingKeys.push(e);
+			_keyEvents.push(e);
 			break;
 
 		case Common::EVENT_KEYUP:
 			updateKeys(e, false);
-			_pendingKeys.push(e);
 			break;
 
 		default:
@@ -93,6 +92,7 @@ void EventsManager::pollEvents() {
 	}
 }
 
+#if 0
 bool EventsManager::keypressed() {
 	pollEvents();
 	return !_pendingKeys.empty();
@@ -104,6 +104,7 @@ Common::Event EventsManager::readKey() {
 	pollEvents();
 	return _pendingKeys.empty() ? Common::Event() : _pendingKeys.pop();
 }
+#endif
 
 Common::Event EventsManager::readEvent() {
 	pollEvents();
@@ -151,40 +152,21 @@ bool EventsManager::isExtendedKey(const Common::KeyCode &keycode) const {
 }
 
 void EventsManager::updateKeys(const Common::Event &event, bool isDown) {
-	// Update the keys array with whether the key is pressed
-	
-	AGS3::eAGSKeyCode key = ags_keycode_from_scummvm(event);
-	if (key != 0)
-		_keys[key] = isDown;
-}
+	_keyModifierFlags = event.kbd.flags;
 
-uint EventsManager::getModifierFlags() const {
-	if (_pendingKeys.empty())
-		return 0;
-
-	byte flags = _pendingKeys.front().kbd.flags;
-	uint keyFlags = 0;
-	if (flags & Common::KBD_SHIFT)
-		keyFlags |= AGS3::__allegro_KB_SHIFT_FLAG;
-	if (flags & Common::KBD_CTRL)
-		keyFlags |= AGS3::__allegro_KB_CTRL_FLAG;
-	if (flags & Common::KBD_ALT)
-		keyFlags |= AGS3::__allegro_KB_ALT_FLAG;
-	if (flags & Common::KBD_META)
-		keyFlags |= AGS3::__allegro_KB_COMMAND_FLAG;
-	if (flags & Common::KBD_SCRL)
-		keyFlags |= AGS3::__allegro_KB_SCROLOCK_FLAG;
-	if (flags & Common::KBD_NUM)
-		keyFlags |= AGS3::__allegro_KB_NUMLOCK_FLAG;
-	if (flags & Common::KBD_CAPS)
-		keyFlags |= AGS3::__allegro_KB_CAPSLOCK_FLAG;
-
-	return keyFlags;
+	_keys[event.kbd.keycode] = isDown;
 }
 
 bool EventsManager::isKeyPressed(AGS3::eAGSKeyCode key) {
 	pollEvents();
-	return _keys[key];
+
+	Common::KeyCode kc[3];
+	if (!ags_key_to_scancode(key, kc))
+		return false;
+
+	return (kc[0] != Common::KEYCODE_INVALID && _keys[kc[0]]) ||
+		(kc[1] != Common::KEYCODE_INVALID && _keys[kc[1]]) ||
+		(kc[2] != Common::KEYCODE_INVALID && _keys[kc[2]]);
 }
 
 bool EventsManager::ags_key_to_scancode(AGS3::eAGSKeyCode key, Common::KeyCode(&kc)[3]) {
diff --git a/engines/ags/events.h b/engines/ags/events.h
index db58c1fc44..5a69c66896 100644
--- a/engines/ags/events.h
+++ b/engines/ags/events.h
@@ -23,7 +23,6 @@
 #ifndef AGS_EVENTS_H
 #define AGS_EVENTS_H
 
-#include "lib/allegro/keyboard.h"
 #include "shared/ac/keycode.h"
 #include "common/array.h"
 #include "common/queue.h"
@@ -34,11 +33,12 @@ namespace AGS {
 class EventsManager {
 private:
 	Common::Queue<Common::Event> _pendingEvents;
-	Common::Queue<Common::Event> _pendingKeys;
+	Common::Queue<Common::Event> _keyEvents;
 	Common::Array<bool> _keys;
 	Common::Point _mousePos;
 	int16 _joystickAxis[32];
 	bool _joystickButton[32];
+	byte _keyModifierFlags = 0;
 
 	bool isModifierKey(const Common::KeyCode &keycode) const;
 	bool isExtendedKey(const Common::KeyCode &keycode) const;
@@ -65,21 +65,32 @@ public:
 	void pollEvents();
 
 	/**
-	 * Returns true if a keypress is pending
+	 * Returns true if any unprocessed keyboard events are pending
 	 */
-	bool keypressed();
+	bool keyEventPending() const {
+		return !_keyEvents.empty();
+	}
 
 	/**
-	 * Returns the next keyboard event, if any is pending
+	 * Returns the next pending unprocessed keyboard event
 	 */
-	Common::Event readKey();
+	Common::Event getPendingKeyEvent() {
+		return _keyEvents.pop();
+	}
+
+	/**
+	 * Returns the bitset of currently pressed modifier keys
+	 */
+	uint getModifierFlags() const {
+		return _keyModifierFlags;
+	}
 
 	/**
 	 * Pushes a keydown event into the keypresses queue,
 	 * without updating the key down flag array
 	 */
 	void pushKeyboardEvent(const Common::Event &evt) {
-		_pendingKeys.push(evt);
+		_keyEvents.push(evt);
 	}
 
 	/**
@@ -99,14 +110,9 @@ public:
 
 	void clearEvents() {
 		_pendingEvents.clear();
-		_pendingKeys.clear();
+		_keyEvents.clear();
 	}
 
-	/**
-	 * Returns the bitset of currently pressed modifier keys
-	 */
-	uint getModifierFlags() const;
-
 	/**
 	 * Get the current mouse position
 	 */
diff --git a/engines/ags/lib/allegro.h b/engines/ags/lib/allegro.h
index 1d5689a19f..3f8e5951af 100644
--- a/engines/ags/lib/allegro.h
+++ b/engines/ags/lib/allegro.h
@@ -35,7 +35,6 @@
 #include "ags/lib/allegro/fixed.h"
 #include "ags/lib/allegro/fmaths.h"
 #include "ags/lib/allegro/gfx.h"
-#include "ags/lib/allegro/keyboard.h"
 #include "ags/lib/allegro/mouse.h"
 #include "ags/lib/allegro/system.h"
 #include "ags/lib/allegro/unicode.h"
diff --git a/engines/ags/lib/allegro/keyboard.cpp b/engines/ags/lib/allegro/keyboard.cpp
deleted file mode 100644
index 3783282070..0000000000
--- a/engines/ags/lib/allegro/keyboard.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "ags/lib/allegro/keyboard.h"
-#include "ags/events.h"
-#include "ags/globals.h"
-#include "common/algorithm.h"
-#include "common/textconsole.h"
-#include "common/system.h"
-#include "common/events.h"
-#include "common/textconsole.h"
-
-namespace AGS3 {
-
-int install_keyboard() {
-	return 0;
-}
-
-void remove_keyboard() {
-}
-
-bool keyboard_needs_poll() {
-	// We allow allow keyboard polling in ScummVM
-	return true;
-}
-
-int poll_keyboard() {
-	::AGS::g_events->pollEvents();
-	return 0;
-}
-
-void simulate_keypress(int keycode) {
-	simulate_ukeypress(keycode, keycode);
-}
-
-void simulate_ukeypress(int keycode, int scancode) {
-	Common::Event event;
-
-	event.type = Common::EVENT_KEYDOWN;
-	event.kbd.ascii = scancode;
-	event.kbd.keycode = (Common::KeyCode)keycode;
-	g_system->getEventManager()->pushEvent(event);
-
-	event.type = Common::EVENT_KEYUP;
-	g_system->getEventManager()->pushEvent(event);
-}
-
-bool keypressed() {
-	return ::AGS::g_events->keypressed();
-}
-
-} // namespace AGS3
diff --git a/engines/ags/lib/allegro/keyboard.h b/engines/ags/lib/allegro/keyboard.h
deleted file mode 100644
index 7e75517aee..0000000000
--- a/engines/ags/lib/allegro/keyboard.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AGS_LIB_ALLEGRO_KEYBOARD_H
-#define AGS_LIB_ALLEGRO_KEYBOARD_H
-
-#include "ags/lib/allegro/alconfig.h"
-#include "common/keyboard.h"
-
-namespace AGS3 {
-
-enum AllegroKbdFlag {
-__allegro_KB_SHIFT_FLAG    = 0x0001,
-__allegro_KB_CTRL_FLAG     = 0x0002,
-__allegro_KB_ALT_FLAG      = 0x0004,
-__allegro_KB_LWIN_FLAG     = 0x0008,
-__allegro_KB_RWIN_FLAG     = 0x0010,
-__allegro_KB_MENU_FLAG     = 0x0020,
-__allegro_KB_COMMAND_FLAG  = 0x0040,
-__allegro_KB_SCROLOCK_FLAG = 0x0100,
-__allegro_KB_NUMLOCK_FLAG  = 0x0200,
-__allegro_KB_CAPSLOCK_FLAG = 0x0400,
-__allegro_KB_INALTSEQ_FLAG = 0x0800,
-__allegro_KB_ACCENT1_FLAG  = 0x1000,
-__allegro_KB_ACCENT2_FLAG  = 0x2000,
-__allegro_KB_ACCENT3_FLAG  = 0x4000,
-__allegro_KB_ACCENT4_FLAG  = 0x8000
-};
-
-enum AllegroKbdKeycode {
-__allegro_KEY_A            = 1,
-__allegro_KEY_B            = 2,
-__allegro_KEY_C            = 3,
-__allegro_KEY_D            = 4,
-__allegro_KEY_E            = 5,
-__allegro_KEY_F            = 6,
-__allegro_KEY_G            = 7,
-__allegro_KEY_H            = 8,
-__allegro_KEY_I            = 9,
-__allegro_KEY_J            = 10,
-__allegro_KEY_K            = 11,
-__allegro_KEY_L            = 12,
-__allegro_KEY_M            = 13,
-__allegro_KEY_N            = 14,
-__allegro_KEY_O            = 15,
-__allegro_KEY_P            = 16,
-__allegro_KEY_Q            = 17,
-__allegro_KEY_R            = 18,
-__allegro_KEY_S            = 19,
-__allegro_KEY_T            = 20,
-__allegro_KEY_U            = 21,
-__allegro_KEY_V            = 22,
-__allegro_KEY_W            = 23,
-__allegro_KEY_X            = 24,
-__allegro_KEY_Y            = 25,
-__allegro_KEY_Z            = 26,
-__allegro_KEY_0            = 27,
-__allegro_KEY_1            = 28,
-__allegro_KEY_2            = 29,
-__allegro_KEY_3            = 30,
-__allegro_KEY_4            = 31,
-__allegro_KEY_5            = 32,
-__allegro_KEY_6            = 33,
-__allegro_KEY_7            = 34,
-__allegro_KEY_8            = 35,
-__allegro_KEY_9            = 36,
-__allegro_KEY_0_PAD        = 37,
-__allegro_KEY_1_PAD        = 38,
-__allegro_KEY_2_PAD        = 39,
-__allegro_KEY_3_PAD        = 40,
-__allegro_KEY_4_PAD        = 41,
-__allegro_KEY_5_PAD        = 42,
-__allegro_KEY_6_PAD        = 43,
-__allegro_KEY_7_PAD        = 44,
-__allegro_KEY_8_PAD        = 45,
-__allegro_KEY_9_PAD        = 46,
-__allegro_KEY_F1           = 47,
-__allegro_KEY_F2           = 48,
-__allegro_KEY_F3           = 49,
-__allegro_KEY_F4           = 50,
-__allegro_KEY_F5           = 51,
-__allegro_KEY_F6           = 52,
-__allegro_KEY_F7           = 53,
-__allegro_KEY_F8           = 54,
-__allegro_KEY_F9           = 55,
-__allegro_KEY_F10          = 56,
-__allegro_KEY_F11          = 57,
-__allegro_KEY_F12          = 58,
-__allegro_KEY_ESC          = 59,
-__allegro_KEY_TILDE        = 60,
-__allegro_KEY_MINUS        = 61,
-__allegro_KEY_EQUALS       = 62,
-__allegro_KEY_BACKSPACE    = 63,
-__allegro_KEY_TAB          = 64,
-__allegro_KEY_OPENBRACE    = 65,
-__allegro_KEY_CLOSEBRACE   = 66,
-__allegro_KEY_ENTER        = 67,
-__allegro_KEY_COLON        = 68,
-__allegro_KEY_QUOTE        = 69,
-__allegro_KEY_BACKSLASH    = 70,
-__allegro_KEY_BACKSLASH2   = 71,
-__allegro_KEY_COMMA        = 72,
-__allegro_KEY_STOP         = 73,
-__allegro_KEY_SLASH        = 74,
-__allegro_KEY_SPACE        = 75,
-__allegro_KEY_INSERT       = 76,
-__allegro_KEY_DEL          = 77,
-__allegro_KEY_HOME         = 78,
-__allegro_KEY_END          = 79,
-__allegro_KEY_PGUP         = 80,
-__allegro_KEY_PGDN         = 81,
-__allegro_KEY_LEFT         = 82,
-__allegro_KEY_RIGHT        = 83,
-__allegro_KEY_UP           = 84,
-__allegro_KEY_DOWN         = 85,
-__allegro_KEY_SLASH_PAD    = 86,
-__allegro_KEY_ASTERISK     = 87,
-__allegro_KEY_MINUS_PAD    = 88,
-__allegro_KEY_PLUS_PAD     = 89,
-__allegro_KEY_DEL_PAD      = 90,
-__allegro_KEY_ENTER_PAD    = 91,
-__allegro_KEY_PRTSCR       = 92,
-__allegro_KEY_PAUSE        = 93,
-__allegro_KEY_ABNT_C1      = 94,
-__allegro_KEY_YEN          = 95,
-__allegro_KEY_KANA         = 96,
-__allegro_KEY_CONVERT      = 97,
-__allegro_KEY_NOCONVERT    = 98,
-__allegro_KEY_AT           = 99,
-__allegro_KEY_CIRCUMFLEX   = 100,
-__allegro_KEY_COLON2       = 101,
-__allegro_KEY_KANJI        = 102,
-__allegro_KEY_EQUALS_PAD   = 103,  /* MacOS X */
-__allegro_KEY_BACKQUOTE    = 104,  /* MacOS X */
-__allegro_KEY_SEMICOLON    = 105,  /* MacOS X */
-__allegro_KEY_COMMAND      = 106,  /* MacOS X */
-__allegro_KEY_UNKNOWN1     = 107,
-__allegro_KEY_UNKNOWN2     = 108,
-__allegro_KEY_UNKNOWN3     = 109,
-__allegro_KEY_UNKNOWN4     = 110,
-__allegro_KEY_UNKNOWN5     = 111,
-__allegro_KEY_UNKNOWN6     = 112,
-__allegro_KEY_UNKNOWN7     = 113,
-__allegro_KEY_UNKNOWN8     = 114,
-
-__allegro_KEY_MODIFIERS    = 115,
-
-__allegro_KEY_LSHIFT       = 115,
-__allegro_KEY_RSHIFT       = 116,
-__allegro_KEY_LCONTROL     = 117,
-__allegro_KEY_RCONTROL     = 118,
-__allegro_KEY_ALT          = 119,
-__allegro_KEY_ALTGR        = 120,
-__allegro_KEY_LWIN         = 121,
-__allegro_KEY_RWIN         = 122,
-__allegro_KEY_MENU         = 123,
-__allegro_KEY_SCRLOCK      = 124,
-__allegro_KEY_NUMLOCK      = 125,
-__allegro_KEY_CAPSLOCK     = 126,
-
-__allegro_KEY_MAX          = 127
-};
-
-#define KB_SHIFT_FLAG         __allegro_KB_SHIFT_FLAG
-#define KB_CTRL_FLAG          __allegro_KB_CTRL_FLAG
-#define KB_ALT_FLAG           __allegro_KB_ALT_FLAG
-#define KB_LWIN_FLAG          __allegro_KB_LWIN_FLAG
-#define KB_RWIN_FLAG          __allegro_KB_RWIN_FLAG
-#define KB_MENU_FLAG          __allegro_KB_MENU_FLAG
-#define KB_COMMAND_FLAG       __allegro_KB_COMMAND_FLAG
-#define KB_SCROLOCK_FLAG      __allegro_KB_SCROLOCK_FLAG
-#define KB_NUMLOCK_FLAG       __allegro_KB_NUMLOCK_FLAG
-#define KB_CAPSLOCK_FLAG      __allegro_KB_CAPSLOCK_FLAG
-#define KB_INALTSEQ_FLAG      __allegro_KB_INALTSEQ_FLAG
-#define KB_ACCENT1_FLAG       __allegro_KB_ACCENT1_FLAG
-#define KB_ACCENT2_FLAG       __allegro_KB_ACCENT2_FLAG
-#define KB_ACCENT3_FLAG       __allegro_KB_ACCENT3_FLAG
-#define KB_ACCENT4_FLAG       __allegro_KB_ACCENT4_FLAG
-
-#define KEY_A                 __allegro_KEY_A
-#define KEY_B                 __allegro_KEY_B
-#define KEY_C                 __allegro_KEY_C
-#define KEY_D                 __allegro_KEY_D
-#define KEY_E                 __allegro_KEY_E
-#define KEY_F                 __allegro_KEY_F
-#define KEY_G                 __allegro_KEY_G
-#define KEY_H                 __allegro_KEY_H
-#define KEY_I                 __allegro_KEY_I
-#define KEY_J                 __allegro_KEY_J
-#define KEY_K                 __allegro_KEY_K
-#define KEY_L                 __allegro_KEY_L
-#define KEY_M                 __allegro_KEY_M
-#define KEY_N                 __allegro_KEY_N
-#define KEY_O                 __allegro_KEY_O
-#define KEY_P                 __allegro_KEY_P
-#define KEY_Q                 __allegro_KEY_Q
-#define KEY_R                 __allegro_KEY_R
-#define KEY_S                 __allegro_KEY_S
-#define KEY_T                 __allegro_KEY_T
-#define KEY_U                 __allegro_KEY_U
-#define KEY_V                 __allegro_KEY_V
-#define KEY_W                 __allegro_KEY_W
-#define KEY_X                 __allegro_KEY_X
-#define KEY_Y                 __allegro_KEY_Y
-#define KEY_Z                 __allegro_KEY_Z
-#define KEY_0                 __allegro_KEY_0
-#define KEY_1                 __allegro_KEY_1
-#define KEY_2                 __allegro_KEY_2
-#define KEY_3                 __allegro_KEY_3
-#define KEY_4                 __allegro_KEY_4
-#define KEY_5                 __allegro_KEY_5
-#define KEY_6                 __allegro_KEY_6
-#define KEY_7                 __allegro_KEY_7
-#define KEY_8                 __allegro_KEY_8
-#define KEY_9                 __allegro_KEY_9
-#define KEY_0_PAD             __allegro_KEY_0_PAD
-#define KEY_1_PAD             __allegro_KEY_1_PAD
-#define KEY_2_PAD             __allegro_KEY_2_PAD
-#define KEY_3_PAD             __allegro_KEY_3_PAD
-#define KEY_4_PAD             __allegro_KEY_4_PAD
-#define KEY_5_PAD             __allegro_KEY_5_PAD
-#define KEY_6_PAD             __allegro_KEY_6_PAD
-#define KEY_7_PAD             __allegro_KEY_7_PAD
-#define KEY_8_PAD             __allegro_KEY_8_PAD
-#define KEY_9_PAD             __allegro_KEY_9_PAD
-#define KEY_F1                __allegro_KEY_F1
-#define KEY_F2                __allegro_KEY_F2
-#define KEY_F3                __allegro_KEY_F3
-#define KEY_F4                __allegro_KEY_F4
-#define KEY_F5                __allegro_KEY_F5
-#define KEY_F6                __allegro_KEY_F6
-#define KEY_F7                __allegro_KEY_F7
-#define KEY_F8                __allegro_KEY_F8
-#define KEY_F9                __allegro_KEY_F9
-#define KEY_F10               __allegro_KEY_F10
-#define KEY_F11               __allegro_KEY_F11
-#define KEY_F12               __allegro_KEY_F12
-#define KEY_ESC               __allegro_KEY_ESC
-#define KEY_TILDE             __allegro_KEY_TILDE
-#define KEY_MINUS             __allegro_KEY_MINUS
-#define KEY_EQUALS            __allegro_KEY_EQUALS
-#define KEY_BACKSPACE         __allegro_KEY_BACKSPACE
-#define KEY_TAB               __allegro_KEY_TAB
-#define KEY_OPENBRACE         __allegro_KEY_OPENBRACE
-#define KEY_CLOSEBRACE        __allegro_KEY_CLOSEBRACE
-#define KEY_ENTER             __allegro_KEY_ENTER
-#define KEY_COLON             __allegro_KEY_COLON
-#define KEY_QUOTE             __allegro_KEY_QUOTE
-#define KEY_BACKSLASH         __allegro_KEY_BACKSLASH
-#define KEY_BACKSLASH2        __allegro_KEY_BACKSLASH2
-#define KEY_COMMA             __allegro_KEY_COMMA
-#define KEY_STOP              __allegro_KEY_STOP
-#define KEY_SLASH             __allegro_KEY_SLASH
-#define KEY_SPACE             __allegro_KEY_SPACE
-#define KEY_INSERT            __allegro_KEY_INSERT
-#define KEY_DEL               __allegro_KEY_DEL
-#define KEY_HOME              __allegro_KEY_HOME
-#define KEY_END               __allegro_KEY_END
-#define KEY_PGUP              __allegro_KEY_PGUP
-#define KEY_PGDN              __allegro_KEY_PGDN
-#define KEY_LEFT              __allegro_KEY_LEFT
-#define KEY_RIGHT             __allegro_KEY_RIGHT
-#define KEY_UP                __allegro_KEY_UP
-#define KEY_DOWN              __allegro_KEY_DOWN
-#define KEY_SLASH_PAD         __allegro_KEY_SLASH_PAD
-#define KEY_ASTERISK          __allegro_KEY_ASTERISK
-#define KEY_MINUS_PAD         __allegro_KEY_MINUS_PAD
-#define KEY_PLUS_PAD          __allegro_KEY_PLUS_PAD
-#define KEY_DEL_PAD           __allegro_KEY_DEL_PAD
-#define KEY_ENTER_PAD         __allegro_KEY_ENTER_PAD
-#define KEY_PRTSCR            __allegro_KEY_PRTSCR
-#define KEY_PAUSE             __allegro_KEY_PAUSE
-#define KEY_ABNT_C1           __allegro_KEY_ABNT_C1
-#define KEY_YEN               __allegro_KEY_YEN
-#define KEY_KANA              __allegro_KEY_KANA
-#define KEY_CONVERT           __allegro_KEY_CONVERT
-#define KEY_NOCONVERT         __allegro_KEY_NOCONVERT
-#define KEY_AT                __allegro_KEY_AT
-#define KEY_CIRCUMFLEX        __allegro_KEY_CIRCUMFLEX
-#define KEY_COLON2            __allegro_KEY_COLON2
-#define KEY_KANJI             __allegro_KEY_KANJI
-#define KEY_EQUALS_PAD        __allegro_KEY_EQUALS_PAD
-#define KEY_BACKQUOTE         __allegro_KEY_BACKQUOTE
-#define KEY_SEMICOLON         __allegro_KEY_SEMICOLON
-#define KEY_COMMAND           __allegro_KEY_COMMAND
-#define KEY_UNKNOWN1          __allegro_KEY_UNKNOWN1
-#define KEY_UNKNOWN2          __allegro_KEY_UNKNOWN2
-#define KEY_UNKNOWN3          __allegro_KEY_UNKNOWN3
-#define KEY_UNKNOWN4          __allegro_KEY_UNKNOWN4
-#define KEY_UNKNOWN5          __allegro_KEY_UNKNOWN5
-#define KEY_UNKNOWN6          __allegro_KEY_UNKNOWN6
-#define KEY_UNKNOWN7          __allegro_KEY_UNKNOWN7
-#define KEY_UNKNOWN8          __allegro_KEY_UNKNOWN8
-
-#define KEY_MODIFIERS         __allegro_KEY_MODIFIERS
-
-#define KEY_LSHIFT            __allegro_KEY_LSHIFT
-#define KEY_RSHIFT            __allegro_KEY_RSHIFT
-#define KEY_LCONTROL          __allegro_KEY_LCONTROL
-#define KEY_RCONTROL          __allegro_KEY_RCONTROL
-#define KEY_ALT               __allegro_KEY_ALT
-#define KEY_ALTGR             __allegro_KEY_ALTGR
-#define KEY_LWIN              __allegro_KEY_LWIN
-#define KEY_RWIN              __allegro_KEY_RWIN
-#define KEY_MENU              __allegro_KEY_MENU
-#define KEY_SCRLOCK           __allegro_KEY_SCRLOCK
-#define KEY_NUMLOCK           __allegro_KEY_NUMLOCK
-#define KEY_CAPSLOCK          __allegro_KEY_CAPSLOCK
-
-#define KEY_MAX               __allegro_KEY_MAX
-
-AL_FUNC(bool, keyboard_needs_poll, (void));
-AL_FUNC(int, poll_keyboard, (void));
-
-extern int install_keyboard();
-extern void remove_keyboard();
-AL_FUNC(void, simulate_keypress, (int keycode));
-AL_FUNC(void, simulate_ukeypress, (int keycode, int scancode));
-
-AL_FUNC(bool, keypressed, (void));
-
-} // namespace AGS3
-
-#endif
diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index 78ef5d8dfc..a462043716 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -21,7 +21,6 @@ MODULE_OBJS = \
 	lib/allegro/flood.o \
 	lib/allegro/gfx.o \
 	lib/allegro/graphics.o \
-	lib/allegro/keyboard.o \
 	lib/allegro/math.o \
 	lib/allegro/mouse.o \
 	lib/allegro/rotate.o \
diff --git a/engines/ags/plugins/ags_creditz/ags_creditz1.cpp b/engines/ags/plugins/ags_creditz/ags_creditz1.cpp
index 2c40338b4e..b98a9d3564 100644
--- a/engines/ags/plugins/ags_creditz/ags_creditz1.cpp
+++ b/engines/ags/plugins/ags_creditz/ags_creditz1.cpp
@@ -165,6 +165,7 @@ void AGSCreditz1::PauseScroll(ScriptMethodParams &params) {
 
 void AGSCreditz1::ScrollReset(ScriptMethodParams &params) {
 	_state->_credits[0].clear();
+	_state->_creditsRunning = false;
 }
 
 void AGSCreditz1::SetEmptyLineHeight(ScriptMethodParams &params) {


Commit: ef64d0154cc580dedb469793ada6677e74806056
    https://github.com/scummvm/scummvm/commit/ef64d0154cc580dedb469793ada6677e74806056
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:55-07:00

Commit Message:
AGS: Remove deprecated mouse code

Changed paths:
  R engines/ags/lib/allegro/mouse.cpp
  R engines/ags/lib/allegro/mouse.h
    engines/ags/engine/device/mouse_w32.cpp
    engines/ags/engine/device/mouse_w32.h
    engines/ags/lib/allegro.h
    engines/ags/module.mk


diff --git a/engines/ags/engine/device/mouse_w32.cpp b/engines/ags/engine/device/mouse_w32.cpp
index e6f344c25d..ead5ee40e9 100644
--- a/engines/ags/engine/device/mouse_w32.cpp
+++ b/engines/ags/engine/device/mouse_w32.cpp
@@ -20,47 +20,16 @@
  *
  */
 
-//=============================================================================
-//
-// MOUSELIBW32.CPP
-//
-// Library of mouse functions for graphics and text mode
-//
-// (c) 1994 Chris Jones
-// Win32 (allegro) update (c) 1999 Chris Jones
-//
-//=============================================================================
-
 #include "common/util.h"
-#include "ags/shared/core/platform.h"
-
-#define AGS_SIMULATE_RIGHT_CLICK (AGS_PLATFORM_OS_MACOS)
-
-#if AGS_PLATFORM_OS_WINDOWS
-//include <dos.h>
-//include <conio.h>
-//include <process.h>
-#endif
-
-#include "ags/shared/util/wgt2_allg.h"
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
+#include "ags/engine/device/mouse_w32.h"
 #include "ags/engine/ac/game_state.h"
+#include "ags/engine/ac/sys_events.h"
 #include "ags/shared/debugging/out.h"
-#include "ags/engine/device/mouse_w32.h"
 #include "ags/shared/gfx/bitmap.h"
-#include "ags/engine/gfx/gfx_util.h"
 #include "ags/engine/main/graphics_mode.h"
 #include "ags/engine/platform/base/ags_platform_driver.h"
-#include "ags/shared/util/math.h"
+#include "ags/engine/platform/base/sys_main.h"
 #include "ags/globals.h"
-#if AGS_SIMULATE_RIGHT_CLICK
-#include "ags/engine/ac/sys_events.h" // j for ags_iskeypressed
-#endif
 
 namespace AGS3 {
 
@@ -73,21 +42,22 @@ enum {
 
 static const int MB_ARRAY[3] = { 1, 2, 4 };
 
-void mgraphconfine(int x1, int y1, int x2, int y2) {
-	_GP(mouse).ControlRect = Rect(x1, y1, x2, y2);
-	set_mouse_range(_GP(mouse).ControlRect.Left, _GP(mouse).ControlRect.Top, _GP(mouse).ControlRect.Right, _GP(mouse).ControlRect.Bottom);
-	Debug::Printf("Mouse confined: (%d,%d)-(%d,%d) (%dx%d)",
-	              _GP(mouse).ControlRect.Left, _GP(mouse).ControlRect.Top, _GP(mouse).ControlRect.Right, _GP(mouse).ControlRect.Bottom,
-	              _GP(mouse).ControlRect.GetWidth(), _GP(mouse).ControlRect.GetHeight());
-}
-
 void mgetgraphpos() {
-	poll_mouse();
+	// TODO: review and possibly rewrite whole thing;
+	// research what disable_mgetgraphpos does, and is this still necessary?
+	// disable or update mouse speed control to sdl
+	// (does sdl support mouse cursor speed? is it even necessary anymore?);
+
+	// TODO: [sonneveld] find out where mgetgraphpos is needed, are events polled before that?
+	sys_evt_process_pending();
+
 	if (_G(disable_mgetgraphpos)) {
 		// The cursor coordinates are provided from alternate source;
 		// in this case we completely ignore actual cursor movement.
 		if (!_G(ignore_bounds) &&
-		        (_G(mousex) < _G(boundx1) || _G(mousey) < _G(boundy1) || _G(mousex) > _G(boundx2) || _G(mousey) > _G(boundy2))) {
+			// When applying script bounds we only do so while cursor is inside game viewport
+			_GP(mouse).ControlRect.IsInside(_G(mousex), _G(mousey)) &&
+			(_G(mousex) < _G(boundx1) || _G(mousey) < _G(boundy1) || _G(mousex) > _G(boundx2) || _G(mousey) > _G(boundy2))) {
 			_G(mousex) = CLIP(_G(mousex), _G(boundx1), _G(boundx2));
 			_G(mousey) = CLIP(_G(mousey), _G(boundy1), _G(boundy2));
 			msetgraphpos(_G(mousex), _G(mousey));
@@ -96,47 +66,15 @@ void mgetgraphpos() {
 	}
 
 	if (!_G(switched_away) && _GP(mouse).ControlEnabled) {
-		// Control mouse movement by querying mouse mickeys (movement deltas)
-		// and applying them to saved mouse coordinates.
-		int mickey_x, mickey_y;
-		get_mouse_mickeys(&mickey_x, &mickey_y);
-
-		// Apply mouse speed
-		int dx = _GP(mouse).Speed * mickey_x;
-		int dy = _GP(mouse).Speed * mickey_y;
-
-		//
-		// Perform actual cursor update
-		//---------------------------------------------------------------------
-		// If the real cursor is inside the control rectangle (read - game window),
-		// then apply sensitivity factors and adjust real cursor position
-		if (_GP(mouse).ControlRect.IsInside(_G(real_mouse_x) + dx, _G(real_mouse_y) + dy)) {
-			_G(real_mouse_x) += dx;
-			_G(real_mouse_y) += dy;
-			position_mouse(_G(real_mouse_x), _G(real_mouse_y));
-		}
-		// Otherwise, if real cursor was moved outside the control rect, yet we
-		// are required to confine cursor inside one, then adjust cursor position
-		// to stay inside the rect's bounds.
-		else if (_GP(mouse).ConfineInCtrlRect) {
-			_G(real_mouse_x) = CLIP(_G(real_mouse_x) + dx, _GP(mouse).ControlRect.Left, _GP(mouse).ControlRect.Right);
-			_G(real_mouse_y) = CLIP(_G(real_mouse_y) + dy, _GP(mouse).ControlRect.Top, _GP(mouse).ControlRect.Bottom);
-			position_mouse(_G(real_mouse_x), _G(real_mouse_y));
-		}
-		// Lastly, if the real cursor is out of the control rect, simply add
-		// actual movement to keep up with the system cursor coordinates.
-		else {
-			_G(real_mouse_x) += mickey_x;
-			_G(real_mouse_y) += mickey_y;
-		}
-
-		// Do not update the game cursor if the real cursor is beyond the control rect
-		if (!_GP(mouse).ControlRect.IsInside(_G(real_mouse_x), _G(real_mouse_y)))
-			return;
+		// Use relative mouse movement; speed factor should already be applied by SDL in this mode
+		int rel_x, rel_y;
+		ags_mouse_get_relxy(rel_x, rel_y);
+		_G(real_mouse_x) = CLIP(_G(real_mouse_x) + rel_x, _GP(mouse).ControlRect.Left, _GP(mouse).ControlRect.Right);
+		_G(real_mouse_y) = CLIP(_G(real_mouse_y) + rel_y, _GP(mouse).ControlRect.Top, _GP(mouse).ControlRect.Bottom);
 	} else {
 		// Save real cursor coordinates provided by system
-		_G(real_mouse_x) = _G(mouse_x);
-		_G(real_mouse_y) = _G(mouse_y);
+		_G(real_mouse_x) = _G(sys_mouse_x);
+		_G(real_mouse_y) = _G(sys_mouse_y);
 	}
 
 	// Set new in-game cursor position
@@ -144,14 +82,16 @@ void mgetgraphpos() {
 	_G(mousey) = _G(real_mouse_y);
 
 	if (!_G(ignore_bounds) &&
-	        (_G(mousex) < _G(boundx1) || _G(mousey) < _G(boundy1) || _G(mousex) > _G(boundx2) || _G(mousey) > _G(boundy2))) {
-		_G(mousex) = CLIP(_G(mousex), _G(boundx1), _G(boundx2));
-		_G(mousey) = CLIP(_G(mousey), _G(boundy1), _G(boundy2));
+		// When applying script bounds we only do so while cursor is inside game viewport
+		_GP(mouse).ControlRect.IsInside(_G(mousex), _G(mousey)) &&
+		(_G(mousex) < _G(boundx1) || _G(mousey) < _G(boundy1) || _G(mousex) > _G(boundx2) || _G(mousey) > _G(boundy2))) {
+		_G(mousex) = Math::Clamp(_G(mousex), _G(boundx1), _G(boundx2));
+		_G(mousey) = Math::Clamp(_G(mousey), _G(boundy1), _G(boundy2));
 		msetgraphpos(_G(mousex), _G(mousey));
 	}
 
 	// Convert to virtual coordinates
-	_GP(mouse).AdjustPosition(_G(mousex), _G(mousey));
+	_GP(mouse).WindowToGame(_G(mousex), _G(mousey));
 }
 
 void msetcursorlimit(int x1, int y1, int x2, int y2) {
@@ -162,10 +102,6 @@ void msetcursorlimit(int x1, int y1, int x2, int y2) {
 }
 
 void domouse(int str) {
-	/*
-	   TO USE THIS ROUTINE YOU MUST LOAD A MOUSE CURSOR USING mloadcursor.
-	   YOU MUST ALSO REMEMBER TO CALL mfreemem AT THE END OF THE PROGRAM.
-	*/
 	int poow = _G(mousecurs)[(int)_G(currentcursor)]->GetWidth();
 	int pooh = _G(mousecurs)[(int)_G(currentcursor)]->GetHeight();
 	//int smx = _G(mousex) - _G(hotxwas), smy = _G(mousey) - _G(hotywas);
@@ -187,66 +123,10 @@ void domouse(int str) {
 	_G(hotywas) = _G(hoty);
 }
 
-int ismouseinbox(int lf, int tp, int rt, int bt) {
-	if ((_G(mousex) >= lf) & (_G(mousex) <= rt) & (_G(mousey) >= tp) & (_G(mousey) <= bt))
-		return TRUE;
-	else
-		return FALSE;
-}
-
-void mfreemem() {
-	for (int re = 0; re < _G(numcurso); re++) {
-		delete _G(mousecurs)[re];
-	}
-}
-
-void mloadwcursor(char *namm) {
-#ifdef TODO
-	color dummypal[256];
-	if (wloadsprites(&dummypal[0], namm, _G(mousecurs), 0, MAXCURSORS)) {
-		error("mloadwcursor: Error reading mouse cursor file");
-	}
-#endif
-}
-
-#ifdef TODO
-int mgetbutton() {
-	int toret = NONE;
-	poll_mouse();
-	int butis = _G(mouse_b);
-
-	if ((butis > 0) & (_G(butwas) > 0))
-		return NONE;  // don't allow holding button down
-
-	if (butis & 1) {
-		toret = LEFT;
-#if AGS_SIMULATE_RIGHT_CLICK
-		// j Ctrl-left click should be right-click
-		if (ags_iskeypressed(__allegro_KEY_LCONTROL) || ags_iskeypressed(__allegro_KEY_RCONTROL)) {
-			toret = RIGHT;
-		}
-#endif
-	} else if (butis & 2)
-		toret = RIGHT;
-	else if (butis & 4)
-		toret = MIDDLE;
-
-	_G(butwas) = butis;
-	return toret;
-}
-#endif
-
-int misbuttondown(int buno) {
-	poll_mouse();
-	if (_G(mouse_b) & MB_ARRAY[buno])
-		return TRUE;
-	return FALSE;
-}
-
 void msetgraphpos(int xa, int ya) {
 	_G(real_mouse_x) = xa;
 	_G(real_mouse_y) = ya;
-	position_mouse(_G(real_mouse_x), _G(real_mouse_y));
+	sys_window_set_mouse(_G(real_mouse_x), _G(real_mouse_y));
 }
 
 void msethotspot(int xx, int yy) {
@@ -255,19 +135,15 @@ void msethotspot(int xx, int yy) {
 }
 
 int minstalled() {
-	return install_mouse();
+	// Number of buttons supported
+	return 3;
 }
 
-void Mouse::AdjustPosition(int &x, int &y) {
+void Mouse::WindowToGame(int &x, int &y) {
 	x = _GP(GameScaling).X.UnScalePt(x) - _GP(play).GetMainViewport().Left;
 	y = _GP(GameScaling).Y.UnScalePt(y) - _GP(play).GetMainViewport().Top;
 }
 
-void Mouse::SetGraphicArea() {
-	Rect dst_r = _GP(GameScaling).ScaleRange(_GP(play).GetMainViewport());
-	mgraphconfine(dst_r.Left, dst_r.Top, dst_r.Right, dst_r.Bottom);
-}
-
 void Mouse::SetMoveLimit(const Rect &r) {
 	Rect src_r = OffsetRect(r, _GP(play).GetMainViewport().GetLT());
 	Rect dst_r = _GP(GameScaling).ScaleRange(src_r);
@@ -293,25 +169,15 @@ void Mouse::UnlockFromWindow() {
 	LockedToWindow = false;
 }
 
-void Mouse::EnableControl(bool confine) {
-	ControlEnabled = true;
-	ConfineInCtrlRect = confine;
-}
-
-void Mouse::DisableControl() {
-	ControlEnabled = false;
-	ConfineInCtrlRect = false;
-}
-
-bool Mouse::IsControlEnabled() {
-	return ControlEnabled;
-}
-
 void Mouse::SetSpeedUnit(float f) {
 	SpeedUnit = f;
 	Speed = SpeedVal / SpeedUnit;
 }
 
+bool Mouse::IsControlEnabled() const {
+	return ControlEnabled;
+}
+
 float Mouse::GetSpeedUnit() {
 	return SpeedUnit;
 }
diff --git a/engines/ags/engine/device/mouse_w32.h b/engines/ags/engine/device/mouse_w32.h
index 1ff87e5a4a..feb0617da4 100644
--- a/engines/ags/engine/device/mouse_w32.h
+++ b/engines/ags/engine/device/mouse_w32.h
@@ -20,17 +20,6 @@
  *
  */
 
-//=============================================================================
-//
-// MOUSELIBW32.CPP
-//
-// Library of mouse functions for graphics and text mode
-//
-// (c) 1994 Chris Jones
-// Win32 (allegro) update (c) 1999 Chris Jones
-//
-//=============================================================================
-
 #ifndef AGS_ENGINE_DEVICE_MOUSEW32_H
 #define AGS_ENGINE_DEVICE_MOUSEW32_H
 
@@ -47,15 +36,10 @@ class Bitmap;
 using namespace AGS; // FIXME later
 
 void msetgraphpos(int, int);
-// Sets the area of the screen within which the mouse can move
-void mgraphconfine(int x1, int y1, int x2, int y2);
 void mgetgraphpos();
 // Sets the area of the game frame (zero-based coordinates) where the mouse cursor is allowed to move;
 // this function was meant to be used to achieve gameplay effect
 void msetcursorlimit(int x1, int y1, int x2, int y2);
-int ismouseinbox(int lf, int tp, int rt, int bt);
-void mfreemem();
-void mloadwcursor(char *namm);
 void msetgraphpos(int xa, int ya);
 void msethotspot(int xx, int yy);
 int minstalled();
@@ -78,7 +62,7 @@ struct Mouse {
 	float Speed = 1.f;
 
 
-	void AdjustPosition(int &x, int &y);
+	void WindowToGame(int &x, int &y);
 
 	// Get if mouse is locked to the game window
 	bool IsLockedToWindow();
@@ -87,12 +71,8 @@ struct Mouse {
 	// Unlock mouse from the game window
 	void UnlockFromWindow();
 
-	// Enable mouse movement control
-	void EnableControl(bool confine);
-	// Disable mouse movement control
-	void DisableControl();
 	// Tell if the mouse movement control is enabled
-	bool IsControlEnabled();
+	bool IsControlEnabled() const;
 	// Set base speed factor, which would serve as a mouse speed unit
 	void SetSpeedUnit(float f);
 	// Get base speed factor
@@ -102,9 +82,6 @@ struct Mouse {
 	// Get speed factor
 	float GetSpeed();
 
-	// Updates limits of the area inside which the standard OS cursor is not shown;
-	// uses game's main viewport (in native coordinates) to calculate real area on screen
-	void SetGraphicArea();
 	// Limits the area where the game cursor can move on virtual screen;
 	// parameter must be in native game coordinates
 	void SetMoveLimit(const Rect &r);
diff --git a/engines/ags/lib/allegro.h b/engines/ags/lib/allegro.h
index 3f8e5951af..c7cc0096b0 100644
--- a/engines/ags/lib/allegro.h
+++ b/engines/ags/lib/allegro.h
@@ -35,7 +35,6 @@
 #include "ags/lib/allegro/fixed.h"
 #include "ags/lib/allegro/fmaths.h"
 #include "ags/lib/allegro/gfx.h"
-#include "ags/lib/allegro/mouse.h"
 #include "ags/lib/allegro/system.h"
 #include "ags/lib/allegro/unicode.h"
 
@@ -44,6 +43,7 @@ namespace AGS3 {
 inline int install_allegro() {
 	return 0;
 }
+
 inline void allegro_exit() {}
 
 } // namespace AGS3
diff --git a/engines/ags/lib/allegro/mouse.cpp b/engines/ags/lib/allegro/mouse.cpp
deleted file mode 100644
index 64ae3da208..0000000000
--- a/engines/ags/lib/allegro/mouse.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "ags/lib/allegro/mouse.h"
-#include "ags/events.h"
-#include "ags/globals.h"
-#include "common/textconsole.h"
-
-namespace AGS3 {
-
-static bool isMouseButtonDown(Common::EventType type) {
-	return type == Common::EVENT_LBUTTONDOWN || type == Common::EVENT_MBUTTONDOWN ||
-	       type == Common::EVENT_RBUTTONDOWN;
-}
-
-static bool isMouseButtonUp(Common::EventType type) {
-	return type == Common::EVENT_LBUTTONUP || type == Common::EVENT_MBUTTONUP ||
-	       type == Common::EVENT_RBUTTONUP;
-}
-
-static bool isMouseWheel(Common::EventType type) {
-	return type == Common::EVENT_WHEELDOWN || type == Common::EVENT_WHEELUP;
-}
-
-static bool isMouseEvent(Common::EventType type) {
-	return type == Common::EVENT_MOUSEMOVE || isMouseButtonDown(type) ||
-	       isMouseButtonUp(type) || isMouseWheel(type);
-}
-
-
-int install_mouse() {
-	_G(mouse_x) = _G(mouse_y) = _G(mouse_z) = 0;
-	_G(mouse_b) = 0;
-	_G(mouse_pos) = 0;
-
-	return 0;
-}
-
-void remove_mouse() {
-}
-
-int poll_mouse() {
-	::AGS::g_events->pollEvents();
-
-	Common::Event e;
-	while ((e = ::AGS::g_events->readEvent()).type != Common::EVENT_INVALID) {
-		if (isMouseEvent(e.type)) {
-			_G(mouse_x) = e.mouse.x;
-			_G(mouse_y) = e.mouse.y;
-			_G(mouse_pos) = (e.mouse.x << 16) | e.mouse.y;
-		}
-
-		switch (e.type) {
-		case Common::EVENT_LBUTTONDOWN:
-			_G(mouse_b) |= 1;
-			break;
-		case Common::EVENT_LBUTTONUP:
-			_G(mouse_b) &= ~1;
-			break;
-		case Common::EVENT_RBUTTONDOWN:
-			_G(mouse_b) |= 2;
-			break;
-		case Common::EVENT_RBUTTONUP:
-			_G(mouse_b) &= ~2;
-			break;
-		case Common::EVENT_MBUTTONDOWN:
-			_G(mouse_b) |= 4;
-			break;
-		case Common::EVENT_MBUTTONUP:
-			_G(mouse_b) &= ~4;
-			break;
-		case Common::EVENT_WHEELDOWN:
-			++_G(mouse_z);
-			break;
-		case Common::EVENT_WHEELUP:
-			--_G(mouse_z);
-			break;
-		default:
-			break;
-		}
-	}
-
-	return 0;
-}
-
-int mouse_needs_poll() {
-	// We can always poll mouse in ScummVM
-	return true;
-}
-
-void enable_hardware_cursor() {
-}
-
-void disable_hardware_cursor() {
-}
-
-void show_mouse(BITMAP *bmp) {
-	warning("TODO: show_mouse");
-}
-
-void scare_mouse() {
-}
-
-void scare_mouse_area(int x, int y, int w, int h) {
-}
-
-void unscare_mouse() {
-}
-
-void position_mouse(int x, int y) {
-	_G(mouse_x) = x;
-	_G(mouse_y) = y;
-	_G(mouse_pos) = (x << 16) | y;
-	::AGS::g_events->warpMouse(Common::Point(x, y));
-}
-
-void position_mouse_z(int z) {
-	_G(mouse_z) = z;
-}
-
-void set_mouse_range(int x1, int y_1, int x2, int y2) {
-}
-
-void set_mouse_speed(int xspeed, int yspeed) {
-}
-
-void select_mouse_cursor(int cursor) {
-}
-
-void set_mouse_cursor_bitmap(int cursor, BITMAP *bmp) {
-}
-
-void set_mouse_sprite_focus(int x, int y) {
-}
-
-void get_mouse_mickeys(int *mickeyx, int *mickeyy) {
-}
-
-void set_mouse_sprite(BITMAP *sprite) {
-}
-
-int show_os_cursor(int cursor) {
-	return 0;
-}
-
-int mouse_on_screen() {
-	return 0;
-}
-
-} // namespace AGS3
diff --git a/engines/ags/lib/allegro/mouse.h b/engines/ags/lib/allegro/mouse.h
deleted file mode 100644
index e45b4b824f..0000000000
--- a/engines/ags/lib/allegro/mouse.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AGS_LIB_ALLEGRO_MOUSE_H
-#define AGS_LIB_ALLEGRO_MOUSE_H
-
-#include "common/events.h"
-#include "ags/lib/allegro/base.h"
-#include "ags/lib/allegro/alconfig.h"
-#include "ags/lib/allegro/gfx.h"
-
-namespace AGS3 {
-
-#define MOUSEDRV_AUTODETECT  -1
-#define MOUSEDRV_NONE         0
-
-AL_FUNC(int, install_mouse, (void));
-AL_FUNC(void, remove_mouse, (void));
-
-AL_FUNC(int, poll_mouse, (void));
-AL_FUNC(int, mouse_needs_poll, (void));
-
-AL_FUNC(void, enable_hardware_cursor, (void));
-AL_FUNC(void, disable_hardware_cursor, (void));
-
-/* Mouse cursors */
-#define MOUSE_CURSOR_NONE        0
-#define MOUSE_CURSOR_ALLEGRO     1
-#define MOUSE_CURSOR_ARROW       2
-#define MOUSE_CURSOR_BUSY        3
-#define MOUSE_CURSOR_QUESTION    4
-#define MOUSE_CURSOR_EDIT        5
-#define AL_NUM_MOUSE_CURSORS        6
-
-#define MOUSE_FLAG_MOVE             1
-#define MOUSE_FLAG_LEFT_DOWN        2
-#define MOUSE_FLAG_LEFT_UP          4
-#define MOUSE_FLAG_RIGHT_DOWN       8
-#define MOUSE_FLAG_RIGHT_UP         16
-#define MOUSE_FLAG_MIDDLE_DOWN      32
-#define MOUSE_FLAG_MIDDLE_UP        64
-#define MOUSE_FLAG_MOVE_Z           128
-#define MOUSE_FLAG_MOVE_W           256
-
-AL_FUNCPTR(void, mouse_callback, (int flags));
-
-AL_FUNC(void, show_mouse, (BITMAP *bmp));
-AL_FUNC(void, scare_mouse, (void));
-AL_FUNC(void, scare_mouse_area, (int x, int y, int w, int h));
-AL_FUNC(void, unscare_mouse, (void));
-AL_FUNC(void, position_mouse, (int x, int y));
-AL_FUNC(void, position_mouse_z, (int z));
-AL_FUNC(void, set_mouse_range, (int x1, int y_1, int x2, int y2));
-AL_FUNC(void, set_mouse_speed, (int xspeed, int yspeed));
-AL_FUNC(void, select_mouse_cursor, (int cursor));
-AL_FUNC(void, set_mouse_cursor_bitmap, (int cursor, BITMAP *bmp));
-AL_FUNC(void, set_mouse_sprite_focus, (int x, int y));
-AL_FUNC(void, get_mouse_mickeys, (int *mickeyx, int *mickeyy));
-AL_FUNC(void, set_mouse_sprite, (BITMAP *sprite));
-AL_FUNC(int, show_os_cursor, (int cursor));
-AL_FUNC(int, mouse_on_screen, (void));
-
-} // namespace AGS3
-
-#endif
diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index a462043716..2f821ff8d8 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -22,7 +22,6 @@ MODULE_OBJS = \
 	lib/allegro/gfx.o \
 	lib/allegro/graphics.o \
 	lib/allegro/math.o \
-	lib/allegro/mouse.o \
 	lib/allegro/rotate.o \
 	lib/allegro/surface.o \
 	lib/allegro/system.o \


Commit: 4c5149960b601c1b3df5aa07e7a4d3c0d5bbbc3c
    https://github.com/scummvm/scummvm/commit/4c5149960b601c1b3df5aa07e7a4d3c0d5bbbc3c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:55-07:00

Commit Message:
AGS: Fix size of returned assets as ScummVM streams

Changed paths:
    engines/ags/shared/core/asset_manager.cpp


diff --git a/engines/ags/shared/core/asset_manager.cpp b/engines/ags/shared/core/asset_manager.cpp
index 0c56332780..cd622bab74 100644
--- a/engines/ags/shared/core/asset_manager.cpp
+++ b/engines/ags/shared/core/asset_manager.cpp
@@ -282,17 +282,17 @@ Common::SeekableReadStream *AssetManager::OpenAssetStream(const String &asset_na
 }
 
 Common::SeekableReadStream *AssetManager::OpenAssetStream(const String &asset_name, const String &filter) const {
-	Stream *stream = OpenAsset(asset_name, filter);
+	soff_t assetSize;
+	Stream *stream = OpenAsset(asset_name, filter, &assetSize);
 	if (!stream)
 		return nullptr;
 
 	// Get the contents of the asset
-	size_t dataSize = stream->GetLength();
-	byte *data = (byte *)malloc(dataSize);
-	stream->Read(data, dataSize);
+	byte *data = (byte *)malloc(assetSize);
+	stream->Read(data, assetSize);
 	delete stream;
 
-	return new Common::MemoryReadStream(data, dataSize, DisposeAfterUse::YES);
+	return new Common::MemoryReadStream(data, assetSize, DisposeAfterUse::YES);
 }
 
 String GetAssetErrorText(AssetError err) {


Commit: 28e2ec6cb26deac0df6eda0f54c8d08048d36e64
    https://github.com/scummvm/scummvm/commit/28e2ec6cb26deac0df6eda0f54c8d08048d36e64
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:56-07:00

Commit Message:
AGS: Savegame fixes

Changed paths:
    engines/ags/engine/ac/game.cpp


diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 1eda29cf6b..ca7d5e4742 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/memstream.h"
 #include "ags/engine/ac/game.h"
 #include "ags/shared/ac/common.h"
 #include "ags/shared/ac/view.h"
@@ -57,6 +58,7 @@
 #include "ags/engine/ac/dynobj/all_script_classes.h"
 #include "ags/engine/ac/dynobj/script_camera.h"
 #include "ags/engine/debugging/debug_log.h"
+#include "ags/engine/debugging/debugger.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/device/mouse_w32.h"
 #include "ags/shared/font/fonts.h"
@@ -848,29 +850,24 @@ void skip_serialized_bitmap(Stream *in) {
 }
 
 long write_screen_shot_for_vista(Stream *out, Bitmap *screenshot) {
-	long fileSize = 0;
-	String tempFileName = String::FromFormat("%s""_tmpscht.bmp", _G(saveGameDirectory).GetCStr());
-
-	screenshot->SaveToFile(tempFileName, _G(palette));
+	// Save the screenshot to a memory stream so we can access the raw data
+	Common::MemoryWriteStreamDynamic bitmap(DisposeAfterUse::YES);
+	screenshot->SaveToFile(bitmap, _G(palette));
 
 	update_polled_stuff_if_runtime();
 
-	if (Path::IsFile(tempFileName)) {
-		fileSize = File::GetFileSize(tempFileName);
-		char *buffer = (char *)malloc(fileSize);
-
-		Stream *temp_in = Shared::File::OpenFileRead(tempFileName);
-		temp_in->Read(buffer, fileSize);
-		delete temp_in;
-		::remove(tempFileName);
+	// Write the bitmap to the output stream
+	out->Write(bitmap.getData(), bitmap.size());
 
-		out->Write(buffer, fileSize);
-		free(buffer);
-	}
-	return fileSize;
+	return bitmap.size();
 }
 
 Bitmap *create_savegame_screenshot() {
+	// Render the view without any UI elements
+	int old_flags = _G(debug_flags);
+	_G(debug_flags) |= DBG_NOIFACE;
+	construct_game_scene(true);
+
 	int usewid = data_to_game_coord(_GP(play).screenshot_width);
 	int usehit = data_to_game_coord(_GP(play).screenshot_height);
 	const Rect &viewport = _GP(play).GetMainViewport();
@@ -882,11 +879,17 @@ Bitmap *create_savegame_screenshot() {
 	if ((_GP(play).screenshot_width < 16) || (_GP(play).screenshot_height < 16))
 		quit("!Invalid _GP(game).screenshot_width/height, must be from 16x16 to screen res");
 
-	return CopyScreenIntoBitmap(usewid, usehit);
+	Bitmap *screenshot = CopyScreenIntoBitmap(usewid, usehit);
+	screenshot->GetAllegroBitmap()->makeOpaque();
+
+	// Restore original screen
+	_G(debug_flags) = old_flags;
+	construct_game_scene(true);
+
+	return screenshot;
 }
 
 void save_game(int slotn, const char *descript) {
-
 	// dont allow save in rep_exec_always, because we dont save
 	// the state of blocked scripts
 	can_run_delayed_command();
@@ -904,7 +907,10 @@ void save_game(int slotn, const char *descript) {
 	VALIDATE_STRING(descript);
 	String nametouse = get_save_game_path(slotn);
 	UBitmap screenShot;
-	if (_GP(game).options[OPT_SAVESCREENSHOT] != 0)
+
+	// WORKAROUND: AGS originally only creates savegames if the game flags
+	// that it supports it. But we want it all the time for ScummVM GMM
+	if (/*_GP(game).options[OPT_SAVESCREENSHOT] != 0*/ true)
 		screenShot.reset(create_savegame_screenshot());
 
 	Engine::UStream out(StartSavegame(nametouse, descript, screenShot.get()));
@@ -924,7 +930,6 @@ void save_game(int slotn, const char *descript) {
 
 		update_polled_stuff_if_runtime();
 
-		out.reset(Shared::File::OpenFile(nametouse, Shared::kFile_Open, Shared::kFile_ReadWrite));
 		out->Seek(12, kSeekBegin);
 		out->WriteInt32(screenShotOffset);
 		out->Seek(4);


Commit: c111ef5f45e1001b39d4d0652169c44415353175
    https://github.com/scummvm/scummvm/commit/c111ef5f45e1001b39d4d0652169c44415353175
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:56-07:00

Commit Message:
AGS: Changing ::remove to File::DeleteFile

Changed paths:
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/debugging/file_based_ags_debugger.cpp
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/quit.cpp
    engines/ags/shared/util/compress.cpp


diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 72155c8166..56ffb7db1a 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "common/savefile.h"
 #include "ags/lib/std/math.h"
 #include "ags/shared/core/platform.h"
 #include "ags/shared/ac/audio_clip_type.h"
@@ -110,19 +111,8 @@ void RestoreGameSlot(int slnum) {
 void DeleteSaveSlot(int slnum) {
 	String nametouse;
 	nametouse = get_save_game_path(slnum);
-	::remove(nametouse);
-	if ((slnum >= 1) && (slnum <= MAXSAVEGAMES)) {
-		String thisname;
-		for (int i = MAXSAVEGAMES; i > slnum; i--) {
-			thisname = get_save_game_path(i);
-			if (Shared::File::TestReadFile(thisname)) {
-				// Rename the highest save game to fill in the gap
-				rename(thisname, nametouse);
-				break;
-			}
-		}
 
-	}
+	g_system->getSavefileManager()->removeSavefile(nametouse);
 }
 
 void PauseGame() {
diff --git a/engines/ags/engine/debugging/file_based_ags_debugger.cpp b/engines/ags/engine/debugging/file_based_ags_debugger.cpp
index 82898a1185..909617cdf9 100644
--- a/engines/ags/engine/debugging/file_based_ags_debugger.cpp
+++ b/engines/ags/engine/debugging/file_based_ags_debugger.cpp
@@ -36,7 +36,7 @@ const char *SENT_MESSAGE_FILE_NAME = "dbgrecv.tmp";
 
 bool FileBasedAGSDebugger::Initialize() {
 	if (Path::IsFile(SENT_MESSAGE_FILE_NAME)) {
-		::remove(SENT_MESSAGE_FILE_NAME);
+		File::DeleteFile(SENT_MESSAGE_FILE_NAME);
 	}
 	return true;
 }
@@ -72,7 +72,7 @@ char *FileBasedAGSDebugger::GetNextMessage() {
 	char *msg = (char *)malloc(fileSize + 1);
 	in->Read(msg, fileSize);
 	delete in;
-	::remove("dbgsend.tmp");
+	File::DeleteFile("dbgsend.tmp");
 	msg[fileSize] = 0;
 	return msg;
 }
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 6b74f25ed9..725178a47c 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -520,7 +520,7 @@ int check_write_access() {
 
 	_G(our_eip) = -1897;
 
-	if (::remove(tempPath))
+	if (File::DeleteFile(tempPath))
 		return 0;
 
 	return 1;
diff --git a/engines/ags/engine/main/quit.cpp b/engines/ags/engine/main/quit.cpp
index bae334e6e9..0eb050264e 100644
--- a/engines/ags/engine/main/quit.cpp
+++ b/engines/ags/engine/main/quit.cpp
@@ -174,7 +174,7 @@ void quit_delete_temp_files() {
 	al_ffblk    dfb;
 	int dun = al_findfirst("~ac*.tmp", &dfb, FA_SEARCH);
 	while (!dun) {
-		::remove(dfb.name);
+		File::DeleteFile(dfb.name);
 		dun = al_findnext(&dfb);
 	}
 	al_findclose(&dfb);
diff --git a/engines/ags/shared/util/compress.cpp b/engines/ags/shared/util/compress.cpp
index 755f852dc7..3877045791 100644
--- a/engines/ags/shared/util/compress.cpp
+++ b/engines/ags/shared/util/compress.cpp
@@ -315,7 +315,7 @@ void save_lzw(Stream *out, const Bitmap *bmpp, const RGB *pall) {
 
 	// Delete temp file
 	delete lz_temp_s;
-	::remove(lztempfnm);
+	File::DeleteFile(lztempfnm);
 
 	// Seek back to the end of the output stream
 	out->Seek(toret, kSeekBegin);


Commit: 6263b9ff11732a07d3f1b36bd95d9867e76c01db
    https://github.com/scummvm/scummvm/commit/6263b9ff11732a07d3f1b36bd95d9867e76c01db
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:56-07:00

Commit Message:
AGS: Do not store keys with null values in the script Dictionary

>From upstream 3c306f46634ff4198189d62bf277765c37f344e5

Changed paths:
    engines/ags/engine/ac/dynobj/script_dict.h


diff --git a/engines/ags/engine/ac/dynobj/script_dict.h b/engines/ags/engine/ac/dynobj/script_dict.h
index 5ac0146793..1dc256ea26 100644
--- a/engines/ags/engine/ac/dynobj/script_dict.h
+++ b/engines/ags/engine/ac/dynobj/script_dict.h
@@ -100,7 +100,7 @@ public:
 	const char *Get(const char *key) override {
 		auto it = _dic.find(String::Wrapper(key));
 		if (it == _dic.end()) return nullptr;
-		return it->_value.GetNullableCStr();
+		return it->_value.GetCStr();
 	}
 	bool Remove(const char *key) override {
 		auto it = _dic.find(String::Wrapper(key));
@@ -110,9 +110,16 @@ public:
 		return true;
 	}
 	bool Set(const char *key, const char *value) override {
-		if (!key) return false;
+		if (!key)
+			return false;
+		if (!value) {
+			// Remove keys with null value
+			Remove(key);
+			return true;
+		}
+
 		size_t key_len = strlen(key);
-		size_t value_len = value ? strlen(value) : 0;
+		size_t value_len = strlen(value);
 		return TryAddItem(key, key_len, value, value_len);
 	}
 	int GetItemCount() override {
@@ -120,19 +127,18 @@ public:
 	}
 	void GetKeys(std::vector<const char *> &buf) const override {
 		for (auto it = _dic.begin(); it != _dic.end(); ++it)
-			buf.push_back(it->_key.GetCStr()); // keys cannot be null
+			buf.push_back(it->_key.GetCStr());
 	}
 	void GetValues(std::vector<const char *> &buf) const override {
 		for (auto it = _dic.begin(); it != _dic.end(); ++it)
-			buf.push_back(it->_value.GetNullableCStr()); // values may be null
+			buf.push_back(it->_value.GetCStr());
 	}
 
 private:
 	bool TryAddItem(const char *key, size_t key_len, const char *value, size_t value_len) {
 		String elem_key(key, key_len);
 		String elem_value;
-		if (value)
-			elem_value.SetString(value, value_len);
+		elem_value.SetString(value, value_len);
 		_dic[elem_key] = elem_value;
 		return true;
 	}
@@ -154,13 +160,10 @@ private:
 			SerializeInt((int)it->_key.GetLength());
 			memcpy(&serbuffer[bytesSoFar], it->_key.GetCStr(), it->_key.GetLength());
 			bytesSoFar += it->_key.GetLength();
-			if (it->_value.GetNullableCStr()) { // values may be null
-				SerializeInt((int)it->_value.GetLength());
-				memcpy(&serbuffer[bytesSoFar], it->_value.GetCStr(), it->_value.GetLength());
-				bytesSoFar += it->_value.GetLength();
-			} else {
-				SerializeInt(-1);
-			}
+
+			SerializeInt((int)it->_value.GetLength());
+			memcpy(&serbuffer[bytesSoFar], it->_value.GetCStr(), it->_value.GetLength());
+			bytesSoFar += it->_value.GetLength();
 		}
 	}
 
@@ -171,9 +174,8 @@ private:
 			int key_pos = bytesSoFar;
 			bytesSoFar += key_len;
 			size_t value_len = UnserializeInt();
-			if (value_len == (size_t)-1) {
-				TryAddItem(&serializedData[key_pos], key_len, nullptr, 0);
-			} else {
+			if (value_len != (size_t)-1) // do not restore keys with null value (old format)
+			{
 				int value_pos = bytesSoFar;
 				bytesSoFar += value_len;
 				TryAddItem(&serializedData[key_pos], key_len, &serializedData[value_pos], value_len);


Commit: 37178efc404daaf841d3cc788d9da9ffb63a9464
    https://github.com/scummvm/scummvm/commit/37178efc404daaf841d3cc788d9da9ffb63a9464
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:57-07:00

Commit Message:
AGS: Common: String::_cstr always non-null, simplified GetCStr()

+ use _len directly in implementation instead of GetLength() (GetCStr
and GetLength in implementation had more complicated meaning in the past).

>From upstream 86eea0873c358a99bf2c1c963057710ef9383b50

Changed paths:
    engines/ags/shared/util/string.cpp
    engines/ags/shared/util/string.h


diff --git a/engines/ags/shared/util/string.cpp b/engines/ags/shared/util/string.cpp
index 5169f1ab6e..690e967cf3 100644
--- a/engines/ags/shared/util/string.cpp
+++ b/engines/ags/shared/util/string.cpp
@@ -31,39 +31,39 @@ namespace AGS {
 namespace Shared {
 
 String::String()
-	: _cstr(nullptr)
+	: _cstr(const_cast<char*>(""))
 	, _len(0)
 	, _buf(nullptr) {
 }
 
 String::String(const String &str)
-	: _cstr(nullptr)
+	: _cstr(const_cast<char*>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	*this = str;
 }
 
 String::String(const char *cstr)
-	: _cstr(nullptr)
+	: _cstr(const_cast<char*>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	*this = cstr;
 }
 
 String::String(const Common::String &s) :
-	_cstr(nullptr), _len(0), _buf(nullptr) {
+	_cstr(const_cast<char*>("")), _len(0), _buf(nullptr) {
 	*this = s.c_str();
 }
 
 String::String(const char *cstr, size_t length)
-	: _cstr(nullptr)
+	: _cstr(const_cast<char*>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	SetString(cstr, length);
 }
 
 String::String(char c, size_t count)
-	: _cstr(nullptr)
+	: _cstr(const_cast<char*>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	FillString(c, count);
@@ -116,15 +116,15 @@ void String::ReadCount(Stream *in, size_t count) {
 
 void String::Write(Stream *out) const {
 	if (out) {
-		out->Write(GetCStr(), GetLength() + 1);
+		out->Write(_cstr, _len + 1);
 	}
 }
 
 void String::WriteCount(Stream *out, size_t count) const {
 	if (out) {
-		size_t str_out_len = Math::Min(count - 1, GetLength());
+		size_t str_out_len = Math::Min(count - 1, _len);
 		if (str_out_len > 0)
-			out->Write(GetCStr(), str_out_len);
+			out->Write(_cstr, str_out_len);
 		size_t null_out_len = count - str_out_len;
 		if (null_out_len > 0)
 			out->WriteByteCount(0, null_out_len);
@@ -139,47 +139,47 @@ void String::WriteCount(Stream *out, size_t count) const {
 }
 
 int String::Compare(const char *cstr) const {
-	return strcmp(GetCStr(), cstr ? cstr : "");
+	return strcmp(_cstr, cstr ? cstr : "");
 }
 
 int String::CompareNoCase(const char *cstr) const {
-	return ags_stricmp(GetCStr(), cstr ? cstr : "");
+	return ags_stricmp(_cstr, cstr ? cstr : "");
 }
 
 int String::CompareLeft(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
-	return strncmp(GetCStr(), cstr, count != npos ? count : strlen(cstr));
+	return strncmp(_cstr, cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareLeftNoCase(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
-	return ags_strnicmp(GetCStr(), cstr, count != npos ? count : strlen(cstr));
+	return ags_strnicmp(_cstr, cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareMid(const char *cstr, size_t from, size_t count) const {
 	cstr = cstr ? cstr : "";
-	from = Math::Min(from, GetLength());
-	return strncmp(GetCStr() + from, cstr, count != npos ? count : strlen(cstr));
+	from = Math::Min(from, _len);
+	return strncmp(_cstr + from, cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareMidNoCase(const char *cstr, size_t from, size_t count) const {
 	cstr = cstr ? cstr : "";
-	from = Math::Min(from, GetLength());
-	return ags_strnicmp(GetCStr() + from, cstr, count != npos ? count : strlen(cstr));
+	from = Math::Min(from, _len);
+	return ags_strnicmp(_cstr + from, cstr, count != npos ? count : strlen(cstr));
 }
 
 int String::CompareRight(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
 	count = count != npos ? count : strlen(cstr);
-	size_t off = Math::Min(GetLength(), count);
-	return strncmp(GetCStr() + GetLength() - off, cstr, count);
+	size_t off = Math::Min(_len, count);
+	return strncmp(_cstr + _len - off, cstr, count);
 }
 
 int String::CompareRightNoCase(const char *cstr, size_t count) const {
 	cstr = cstr ? cstr : "";
 	count = count != npos ? count : strlen(cstr);
-	size_t off = Math::Min(GetLength(), count);
-	return ags_strnicmp(GetCStr() + GetLength() - off, cstr, count);
+	size_t off = Math::Min(_len, count);
+	return ags_strnicmp(_cstr + _len - off, cstr, count);
 }
 
 size_t String::FindChar(char c, size_t from) const {
@@ -191,7 +191,7 @@ size_t String::FindChar(char c, size_t from) const {
 }
 
 size_t String::FindCharReverse(char c, size_t from) const {
-	if (!_cstr || !c) {
+	if ((_len == 0) || !c) {
 		return npos;
 	}
 
@@ -216,7 +216,7 @@ size_t String::FindString(const char *cstr, size_t from) const {
 
 bool String::FindSection(char separator, size_t first, size_t last, bool exclude_first_sep, bool exclude_last_sep,
                          size_t &from, size_t &to) const {
-	if (!_cstr || !separator) {
+	if ((_len == 0) || !separator) {
 		return false;
 	}
 	if (first > last) {
@@ -259,7 +259,7 @@ bool String::FindSection(char separator, size_t first, size_t last, bool exclude
 }
 
 int String::ToInt() const {
-	return atoi(GetCStr());
+	return atoi(_cstr);
 }
 
 String String::Wrapper(const char *cstr) {
@@ -309,22 +309,22 @@ String String::Upper() const {
 }
 
 String String::Left(size_t count) const {
-	count = Math::Min(count, GetLength());
-	return count == GetLength() ? *this : String(GetCStr(), count);
+	count = Math::Min(count, _len);
+	return count == _len ? *this : String(_cstr, count);
 }
 
 String String::Mid(size_t from, size_t count) const {
-	Math::ClampLength(from, count, (size_t)0, GetLength());
-	return count == GetLength() ? *this : String(GetCStr() + from, count);
+	Math::ClampLength(from, count, (size_t)0, _len);
+	return count == _len ? *this : String(_cstr + from, count);
 }
 
 String String::Right(size_t count) const {
-	count = Math::Min(count, GetLength());
-	return count == GetLength() ? *this : String(GetCStr() + GetLength() - count, count);
+	count = Math::Min(count, _len);
+	return count == _len ? *this : String(_cstr + _len - count, count);
 }
 
 String String::LeftSection(char separator, bool exclude_separator) const {
-	if (_cstr && separator) {
+	if ((_len != 0) && separator) {
 		size_t slice_at = FindChar(separator);
 		if (slice_at != npos) {
 			slice_at = exclude_separator ? slice_at : slice_at + 1;
@@ -335,7 +335,7 @@ String String::LeftSection(char separator, bool exclude_separator) const {
 }
 
 String String::RightSection(char separator, bool exclude_separator) const {
-	if (_cstr && separator) {
+	if ((_len != 0) && separator) {
 		size_t slice_at = FindCharReverse(separator);
 		if (slice_at != npos) {
 			size_t count = exclude_separator ? _len - slice_at - 1 : _len - slice_at;
@@ -347,7 +347,7 @@ String String::RightSection(char separator, bool exclude_separator) const {
 
 String String::Section(char separator, size_t first, size_t last,
                        bool exclude_first_sep, bool exclude_last_sep) const {
-	if (!_cstr || !separator) {
+	if ((_len == 0) || !separator) {
 		return String();
 	}
 
@@ -390,7 +390,7 @@ void String::Reserve(size_t max_length) {
 }
 
 void String::ReserveMore(size_t more_length) {
-	Reserve(GetLength() + more_length);
+	Reserve(_len + more_length);
 }
 
 void String::Compact() {
@@ -420,7 +420,7 @@ void String::AppendChar(char c) {
 }
 
 void String::ClipLeft(size_t count) {
-	if (_len > 0 && count > 0) {
+	if (_len != 0 && count > 0) {
 		count = Math::Min(count, _len);
 		BecomeUnique();
 		_len -= count;
@@ -450,7 +450,7 @@ void String::ClipMid(size_t from, size_t count) {
 
 void String::ClipRight(size_t count) {
 	if (count > 0) {
-		count = Math::Min(count, GetLength());
+		count = Math::Min(count, _len);
 		BecomeUnique();
 		_len -= count;
 		_cstr[_len] = 0;
@@ -458,7 +458,7 @@ void String::ClipRight(size_t count) {
 }
 
 void String::ClipLeftSection(char separator, bool include_separator) {
-	if (_cstr && separator) {
+	if ((_len != 0) && separator) {
 		size_t slice_at = FindChar(separator);
 		if (slice_at != npos) {
 			ClipLeft(include_separator ? slice_at + 1 : slice_at);
@@ -468,7 +468,7 @@ void String::ClipLeftSection(char separator, bool include_separator) {
 }
 
 void String::ClipRightSection(char separator, bool include_separator) {
-	if (_cstr && separator) {
+	if ((_len != 0) && separator) {
 		size_t slice_at = FindCharReverse(separator);
 		if (slice_at != npos) {
 			ClipRight(include_separator ? _len - slice_at : _len - slice_at - 1);
@@ -479,7 +479,7 @@ void String::ClipRightSection(char separator, bool include_separator) {
 
 void String::ClipSection(char separator, size_t first, size_t last,
                          bool include_first_sep, bool include_last_sep) {
-	if (!_cstr || !separator) {
+	if ((_len == 0) || !separator) {
 		return;
 	}
 
@@ -492,13 +492,11 @@ void String::ClipSection(char separator, size_t first, size_t last,
 }
 
 void String::Empty() {
-	if (_cstr) {
-		if (IsShared()) {
-			Free();
-		} else {
-			_len = 0;
-			_cstr[0] = 0;
-		}
+	if (IsShared()) {
+		Free();
+	} else {
+		_len = 0;
+		_cstr[0] = 0;
 	}
 }
 
@@ -525,7 +523,7 @@ void String::FormatV(const char *fcstr, va_list argptr) {
 	va_list argptr_cpy;
 	va_copy(argptr_cpy, argptr);
 	size_t length = vsnprintf(nullptr, 0u, fcstr, argptr);
-	ReserveAndShift(false, Math::Surplus(length, GetLength()));
+	ReserveAndShift(false, Math::Surplus(length, _len));
 	vsprintf(_cstr, fcstr, argptr_cpy);
 	va_end(argptr_cpy);
 	_len = length;
@@ -541,26 +539,26 @@ void String::Free() {
 		}
 	}
 	_buf = nullptr;
-	_cstr = nullptr;
+	_cstr = const_cast<char *>("");
 	_len = 0;
 }
 
 void String::MakeLower() {
-	if (_cstr) {
+	if (_len != 0) {
 		BecomeUnique();
 		ags_strlwr(_cstr);
 	}
 }
 
 void String::MakeUpper() {
-	if (_cstr) {
+	if (_len != 0) {
 		BecomeUnique();
 		ags_strupr(_cstr);
 	}
 }
 
 void String::MergeSequences(char c) {
-	if (!_cstr || GetLength() <= 1)
+	if ((_len == 0) || _len <= 1)
 		return;
 	BecomeUnique();
 	char last = 0;
@@ -596,7 +594,7 @@ void String::PrependChar(char c) {
 }
 
 void String::Replace(char what, char with) {
-	if (_cstr && what && with && what != with) {
+	if ((_len != 0) && what && with && what != with) {
 		BecomeUnique();
 		char *rep_ptr = _cstr;
 		while (*rep_ptr) {
@@ -612,16 +610,16 @@ void String::ReplaceMid(size_t from, size_t count, const char *cstr) {
 	if (!cstr)
 		cstr = "";
 	size_t length = strlen(cstr);
-	Math::ClampLength(from, count, (size_t)0, GetLength());
+	Math::ClampLength(from, count, (size_t)0, _len);
 	ReserveAndShift(false, Math::Surplus(length, count));
-	memmove(_cstr + from + length, _cstr + from + count, GetLength() - (from + count) + 1);
+	memmove(_cstr + from + length, _cstr + from + count, _len - (from + count) + 1);
 	memcpy(_cstr + from, cstr, length);
 	_len += length - count;
 }
 
 void String::Reverse() {
-	if (!_cstr || GetLength() <= 1)
-		return;
+	if (_len <= 1)
+		return;	// nothing to reverse if 1 char or less
 	BecomeUnique();
 	for (char *fw = _cstr, *bw = _cstr + _len - 1;
 	        fw < bw; ++fw, --bw) {
@@ -630,7 +628,7 @@ void String::Reverse() {
 }
 
 void String::SetAt(size_t index, char c) {
-	if (_cstr && index < GetLength() && c) {
+	if (_cstr && index < _len && c) {
 		BecomeUnique();
 		_cstr[index] = c;
 	}
@@ -640,7 +638,7 @@ void String::SetString(const char *cstr, size_t length) {
 	if (cstr) {
 		length = Math::Min(length, strlen(cstr));
 		if (length > 0) {
-			ReserveAndShift(false, Math::Surplus(length, GetLength()));
+			ReserveAndShift(false, Math::Surplus(length, _len));
 			memcpy(_cstr, cstr, length);
 			_len = length;
 			_cstr[length] = 0;
@@ -658,7 +656,7 @@ void String::Trim(char c) {
 }
 
 void String::TrimLeft(char c) {
-	if (!_cstr || !_len) {
+	if ((_len == 0) || !_len) {
 		return;
 	}
 
@@ -685,7 +683,7 @@ void String::TrimLeft(char c) {
 }
 
 void String::TrimRight(char c) {
-	if (!_cstr || !_len) {
+	if ((_len == 0) || !_len) {
 		return;
 	}
 
@@ -712,7 +710,7 @@ void String::TrimRight(char c) {
 }
 
 void String::TruncateToLeft(size_t count) {
-	if (_cstr) {
+	if (_len != 0) {
 		count = Math::Min(count, _len);
 		if (count < _len) {
 			BecomeUnique();
@@ -723,7 +721,7 @@ void String::TruncateToLeft(size_t count) {
 }
 
 void String::TruncateToMid(size_t from, size_t count) {
-	if (_cstr) {
+	if (_len != 0) {
 		Math::ClampLength(from, count, (size_t)0, _len);
 		if (from > 0 || count < _len) {
 			BecomeUnique();
@@ -735,8 +733,8 @@ void String::TruncateToMid(size_t from, size_t count) {
 }
 
 void String::TruncateToRight(size_t count) {
-	if (_cstr) {
-		count = Math::Min(count, GetLength());
+	if (_len != 0) {
+		count = Math::Min(count, _len);
 		if (count < _len) {
 			BecomeUnique();
 			_cstr += _len - count;
@@ -746,7 +744,7 @@ void String::TruncateToRight(size_t count) {
 }
 
 void String::TruncateToLeftSection(char separator, bool exclude_separator) {
-	if (_cstr && separator) {
+	if ((_len != 0) && separator) {
 		size_t slice_at = FindChar(separator);
 		if (slice_at != npos) {
 			TruncateToLeft(exclude_separator ? slice_at : slice_at + 1);
@@ -755,7 +753,7 @@ void String::TruncateToLeftSection(char separator, bool exclude_separator) {
 }
 
 void String::TruncateToRightSection(char separator, bool exclude_separator) {
-	if (_cstr && separator) {
+	if ((_len != 0) && separator) {
 		size_t slice_at = FindCharReverse(separator);
 		if (slice_at != npos) {
 			TruncateToRight(exclude_separator ? _len - slice_at - 1 : _len - slice_at);
@@ -765,7 +763,7 @@ void String::TruncateToRightSection(char separator, bool exclude_separator) {
 
 void String::TruncateToSection(char separator, size_t first, size_t last,
                                bool exclude_first_sep, bool exclude_last_sep) {
-	if (!_cstr || !separator) {
+	if ((_len == 0) || !separator) {
 		return;
 	}
 
@@ -817,7 +815,7 @@ void String::Create(size_t max_length) {
 }
 
 void String::Copy(size_t max_length, size_t offset) {
-	if (!_cstr) {
+	if ((_len == 0)) {
 		return;
 	}
 
@@ -841,8 +839,10 @@ void String::Align(size_t offset) {
 	_cstr = cstr_head;
 }
 
-inline bool String::IsShared() const { // if it has a string, and have refcount > 1 or wraps an external char[]
-	return _cstr && ((_bufHead && _bufHead->RefCount > 1) || !_bufHead);
+inline bool String::IsShared() const {
+	// no allocated buffer == wrapping an external char[]
+	// has buffer and refcount > 1 == shared string buffer
+	return !_bufHead || (_bufHead->RefCount > 1);
 }
 
 void String::BecomeUnique() {
diff --git a/engines/ags/shared/util/string.h b/engines/ags/shared/util/string.h
index 223857a88b..4239b5428b 100644
--- a/engines/ags/shared/util/string.h
+++ b/engines/ags/shared/util/string.h
@@ -359,14 +359,14 @@ public:
 
 	// Tells if this object shares its string buffer with others
 	bool    IsShared() const;
-	// Ensure this string is a compact independent copy, with ref counter = 1
+	// Ensure this string is a writeable independent copy, with ref counter = 1
 	void    BecomeUnique();
 	// Ensure this string is independent, and there's enough space before
 	// or after the current string data
 	void    ReserveAndShift(bool left, size_t more_length);
 
-	char *_cstr;  // pointer to actual string data
-	size_t  _len;    // valid string length, in characters, excluding null-term
+	char *_cstr;  // pointer to actual string data; always valid, never null
+	size_t  _len; // valid string length, in characters, excluding null-term
 
 	// Header of a reference-counted buffer
 	struct BufHeader {


Commit: fa482003660111e2c54de55e5ddcf9033c276ff1
    https://github.com/scummvm/scummvm/commit/fa482003660111e2c54de55e5ddcf9033c276ff1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:57-07:00

Commit Message:
AGS: Removed redundant static String::WriteString()

>From upstream 937907f8cf5777071ab78f6050709e3069815ec2

Changed paths:
    engines/ags/shared/util/string.cpp
    engines/ags/shared/util/string.h


diff --git a/engines/ags/shared/util/string.cpp b/engines/ags/shared/util/string.cpp
index 690e967cf3..3090040105 100644
--- a/engines/ags/shared/util/string.cpp
+++ b/engines/ags/shared/util/string.cpp
@@ -131,13 +131,6 @@ void String::WriteCount(Stream *out, size_t count) const {
 	}
 }
 
-/* static */ void String::WriteString(const char *cstr, Stream *out) {
-	if (out) {
-		cstr = cstr ? cstr : "";
-		out->Write(cstr, strlen(cstr) + 1);
-	}
-}
-
 int String::Compare(const char *cstr) const {
 	return strcmp(_cstr, cstr ? cstr : "");
 }
diff --git a/engines/ags/shared/util/string.h b/engines/ags/shared/util/string.h
index 4239b5428b..a50f678d2a 100644
--- a/engines/ags/shared/util/string.h
+++ b/engines/ags/shared/util/string.h
@@ -129,8 +129,6 @@ public:
 	// space with null-terminators when needed.
 	void    WriteCount(Stream *out, size_t count) const;
 
-	static void WriteString(const char *cstr, Stream *out);
-
 	//-------------------------------------------------------------------------
 	// String analysis methods
 	//-------------------------------------------------------------------------


Commit: 91c7eeef144359b905858cc1c0904c3b398d750a
    https://github.com/scummvm/scummvm/commit/91c7eeef144359b905858cc1c0904c3b398d750a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:57-07:00

Commit Message:
AGS: Provided String method variants with "const String&" argument

>From upstream 1e33b06b3329b6b0a79c9fe818c012741c08ae2a

Changed paths:
    engines/ags/ags.cpp
    engines/ags/engine/ac/file.cpp
    engines/ags/shared/util/directory.cpp
    engines/ags/shared/util/file.cpp
    engines/ags/shared/util/file_stream.cpp
    engines/ags/shared/util/string.cpp
    engines/ags/shared/util/string.h
    engines/ags/shared/util/string_types.h


diff --git a/engines/ags/ags.cpp b/engines/ags/ags.cpp
index 08ad6723e6..1c945fe290 100644
--- a/engines/ags/ags.cpp
+++ b/engines/ags/ags.cpp
@@ -158,7 +158,7 @@ Common::Error AGSEngine::run() {
 	if (!_G(justTellInfo))
 		_G(platform)->SetGUIMode(true);
 	AGS3::init_debug(startup_opts, _G(justTellInfo));
-	AGS3::AGS::Shared::Debug::Printf("%s", AGS3::get_engine_string().GetNullableCStr());
+	AGS3::AGS::Shared::Debug::Printf("%s", AGS3::get_engine_string().GetCStr());
 
 	AGS3::main_set_gamedir(ARGC, ARGV);
 
diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index af7969bcac..7862560d84 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -325,13 +325,13 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 		// The Blackwell Legacy write to files in the game folder
 		rp.BaseDir = SAVE_FOLDER_PREFIX;
 		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
-			orig_sc_path.GetNullableCStr());
+			orig_sc_path.GetCStr());
 		rp.AltPath = orig_sc_path;
 	} else {
 		// For writing files, always use as save files
 		rp.BaseDir = SAVE_FOLDER_PREFIX;
 		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
-			orig_sc_path.GetNullableCStr());
+			orig_sc_path.GetCStr());
 	}
 	*/
 	String sc_path = FixSlashAfterToken(orig_sc_path);
diff --git a/engines/ags/shared/util/directory.cpp b/engines/ags/shared/util/directory.cpp
index a7b2066801..df5611fab1 100644
--- a/engines/ags/shared/util/directory.cpp
+++ b/engines/ags/shared/util/directory.cpp
@@ -36,7 +36,7 @@ const char *SAVE_FOLDER_PREFIX = "/saves/";
 namespace Directory {
 
 bool CreateDirectory(const String &path) {
-	return Common::FSNode(path.GetNullableCStr()).createDirectory();
+	return Common::FSNode(path.GetCStr()).createDirectory();
 }
 
 bool CreateAllDirectories(const String &parent, const String &path) {
@@ -65,7 +65,7 @@ bool CreateAllDirectories(const String &parent, const String &path) {
 }
 
 String SetCurrentDirectory(const String &path) {
-	warning("TODO: SetCurrentDirectory: %s", path.GetNullableCStr());
+	warning("TODO: SetCurrentDirectory: %s", path.GetCStr());
 	//  chdir(path);
 	//  return GetCurrentDirectory();
 	return path;
diff --git a/engines/ags/shared/util/file.cpp b/engines/ags/shared/util/file.cpp
index 9da30ad869..b6cf4598e2 100644
--- a/engines/ags/shared/util/file.cpp
+++ b/engines/ags/shared/util/file.cpp
@@ -43,7 +43,7 @@ soff_t File::GetFileSize(const String &filename) {
 bool File::TestReadFile(const String &filename) {
 	if (filename.IsEmpty())
 		return false;
-	return ags_file_exists(filename.GetNullableCStr());
+	return ags_file_exists(filename.GetCStr());
 }
 
 bool File::TestWriteFile(const String &filename) {
diff --git a/engines/ags/shared/util/file_stream.cpp b/engines/ags/shared/util/file_stream.cpp
index 50bbe7b497..2d8d41f1a1 100644
--- a/engines/ags/shared/util/file_stream.cpp
+++ b/engines/ags/shared/util/file_stream.cpp
@@ -177,12 +177,12 @@ void FileStream::Open(const String &file_name, FileOpenMode open_mode, FileWorkM
 	if (open_mode == kFile_Open) {
 		if (!file_name.CompareLeftNoCase(SAVE_FOLDER_PREFIX)) {
 			_file = g_system->getSavefileManager()->openForLoading(
-			            file_name.GetNullableCStr() + strlen(SAVE_FOLDER_PREFIX));
+			            file_name.GetCStr() + strlen(SAVE_FOLDER_PREFIX));
 
 		} else {
 			// First try to open file in game folder
 			Common::File *f = new Common::File();
-			if (!f->open(getFSNode(file_name.GetNullableCStr()))) {
+			if (!f->open(getFSNode(file_name.GetCStr()))) {
 				delete f;
 				_file = nullptr;
 			} else {
diff --git a/engines/ags/shared/util/string.cpp b/engines/ags/shared/util/string.cpp
index 3090040105..f4866058ab 100644
--- a/engines/ags/shared/util/string.cpp
+++ b/engines/ags/shared/util/string.cpp
@@ -31,39 +31,52 @@ namespace AGS {
 namespace Shared {
 
 String::String()
-	: _cstr(const_cast<char*>(""))
+	: _cstr(const_cast<char *>(""))
 	, _len(0)
 	, _buf(nullptr) {
 }
 
 String::String(const String &str)
-	: _cstr(const_cast<char*>(""))
+	: _cstr(const_cast<char *>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	*this = str;
 }
 
+String::String(String &&str) {
+	_cstr = str._cstr;
+	_len = str._len;
+	_buf = str._buf;
+	_bufHead = str._bufHead;
+	str._cstr = const_cast<char *>("");
+	str._len = 0;
+	str._buf = nullptr;
+	str._bufHead = nullptr;
+}
+
 String::String(const char *cstr)
-	: _cstr(const_cast<char*>(""))
+	: _cstr(const_cast<char *>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	*this = cstr;
 }
 
-String::String(const Common::String &s) :
-	_cstr(const_cast<char*>("")), _len(0), _buf(nullptr) {
+String::String(const Common::String &s)
+	: _cstr(nullptr),
+	_len(0),
+	_buf(nullptr) {
 	*this = s.c_str();
 }
 
 String::String(const char *cstr, size_t length)
-	: _cstr(const_cast<char*>(""))
+	: _cstr(const_cast<char *>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	SetString(cstr, length);
 }
 
 String::String(char c, size_t count)
-	: _cstr(const_cast<char*>(""))
+	: _cstr(const_cast<char *>(""))
 	, _len(0)
 	, _buf(nullptr) {
 	FillString(c, count);
@@ -73,6 +86,16 @@ String::~String() {
 	Free();
 }
 
+bool String::IsNullOrSpace() const {
+	if (_len == 0)
+		return true;
+	for (const char *ptr = _cstr; *ptr; ++ptr) {
+		if (!Common::isSpace(*ptr))
+			return false;
+	}
+	return true;
+}
+
 void String::Read(Stream *in, size_t max_chars, bool stop_at_limit) {
 	Empty();
 	if (!in) {
@@ -178,7 +201,7 @@ int String::CompareRightNoCase(const char *cstr, size_t count) const {
 size_t String::FindChar(char c, size_t from) const {
 	if (c && from < _len) {
 		const char *found_cstr = strchr(_cstr + from, c);
-		return found_cstr ? found_cstr - _cstr : -1;
+		return found_cstr ? found_cstr - _cstr : npos;
 	}
 	return npos;
 }
@@ -202,13 +225,13 @@ size_t String::FindCharReverse(char c, size_t from) const {
 size_t String::FindString(const char *cstr, size_t from) const {
 	if (cstr && from < _len) {
 		const char *found_cstr = strstr(_cstr + from, cstr);
-		return found_cstr ? found_cstr - _cstr : -1;
+		return found_cstr ? found_cstr - _cstr : npos;
 	}
 	return npos;
 }
 
 bool String::FindSection(char separator, size_t first, size_t last, bool exclude_first_sep, bool exclude_last_sep,
-                         size_t &from, size_t &to) const {
+	size_t &from, size_t &to) const {
 	if ((_len == 0) || !separator) {
 		return false;
 	}
@@ -257,7 +280,10 @@ int String::ToInt() const {
 
 String String::Wrapper(const char *cstr) {
 	String str;
-	str.Wrap(cstr);
+	// Note that String will NOT *modify* the const buffer.
+	// Any write operation on the buffer is preceded by a call to BecomeUnique.
+	str._cstr = const_cast<char *>(cstr ? cstr : "");
+	str._len = strlen(str._cstr);
 	return str;
 }
 
@@ -339,7 +365,7 @@ String String::RightSection(char separator, bool exclude_separator) const {
 }
 
 String String::Section(char separator, size_t first, size_t last,
-                       bool exclude_first_sep, bool exclude_last_sep) const {
+	bool exclude_first_sep, bool exclude_last_sep) const {
 	if ((_len == 0) || !separator) {
 		return String();
 	}
@@ -347,7 +373,7 @@ String String::Section(char separator, size_t first, size_t last,
 	size_t slice_from;
 	size_t slice_to;
 	if (FindSection(separator, first, last, exclude_first_sep, exclude_last_sep,
-	                slice_from, slice_to)) {
+		slice_from, slice_to)) {
 		return Mid(slice_from, slice_to - slice_from);
 	}
 	return String();
@@ -392,15 +418,13 @@ void String::Compact() {
 	}
 }
 
-void String::Append(const char *cstr) {
-	if (cstr) {
-		size_t length = strlen(cstr);
-		if (length > 0) {
-			ReserveAndShift(false, length);
-			memcpy(_cstr + _len, cstr, length);
-			_len += length;
-			_cstr[_len] = 0;
-		}
+void String::Append(const String &str) {
+	size_t length = str._len;
+	if (str._len > 0) {
+		ReserveAndShift(false, length);
+		memcpy(_cstr + _len, str._cstr, length);
+		_len += length;
+		_cstr[_len] = 0;
 	}
 }
 
@@ -413,7 +437,7 @@ void String::AppendChar(char c) {
 }
 
 void String::ClipLeft(size_t count) {
-	if (_len != 0 && count > 0) {
+	if ((_len != 0) && (count > 0)) {
 		count = Math::Min(count, _len);
 		BecomeUnique();
 		_len -= count;
@@ -471,7 +495,7 @@ void String::ClipRightSection(char separator, bool include_separator) {
 }
 
 void String::ClipSection(char separator, size_t first, size_t last,
-                         bool include_first_sep, bool include_last_sep) {
+	bool include_first_sep, bool include_last_sep) {
 	if ((_len == 0) || !separator) {
 		return;
 	}
@@ -479,7 +503,7 @@ void String::ClipSection(char separator, size_t first, size_t last,
 	size_t slice_from;
 	size_t slice_to;
 	if (FindSection(separator, first, last, !include_first_sep, !include_last_sep,
-	                slice_from, slice_to)) {
+		slice_from, slice_to)) {
 		ClipMid(slice_from, slice_to - slice_from);
 	}
 }
@@ -551,8 +575,8 @@ void String::MakeUpper() {
 }
 
 void String::MergeSequences(char c) {
-	if ((_len == 0) || _len <= 1)
-		return;
+	if (_len <= 1)
+		return; // no point merging if 1 char or less
 	BecomeUnique();
 	char last = 0;
 	char *wp = _cstr;
@@ -565,15 +589,13 @@ void String::MergeSequences(char c) {
 	_len = wp - _cstr;
 }
 
-void String::Prepend(const char *cstr) {
-	if (cstr) {
-		size_t length = strlen(cstr);
-		if (length > 0) {
-			ReserveAndShift(true, length);
-			memcpy(_cstr - length, cstr, length);
-			_len += length;
-			_cstr -= length;
-		}
+void String::Prepend(const String &str) {
+	size_t length = str._len;
+	if (length > 0) {
+		ReserveAndShift(true, length);
+		memcpy(_cstr - length, str._cstr, length);
+		_len += length;
+		_cstr -= length;
 	}
 }
 
@@ -587,41 +609,80 @@ void String::PrependChar(char c) {
 }
 
 void String::Replace(char what, char with) {
-	if ((_len != 0) && what && with && what != with) {
-		BecomeUnique();
-		char *rep_ptr = _cstr;
-		while (*rep_ptr) {
-			if (*rep_ptr == what) {
-				*rep_ptr = with;
+	if ((_len == 0) || !what || !with || (what == with))
+		return;
+	char *ptr = _cstr;
+	// Special case for calling BecomeUnique on the first find
+	if (IsShared()) {
+		for (; *ptr; ++ptr) {
+			if (*ptr == what) {
+				ptrdiff_t diff = ptr - _cstr;
+				BecomeUnique();
+				ptr = _cstr + diff; // BecomeUnique will realloc memory
+				break;
 			}
-			rep_ptr++;
 		}
 	}
+	// Do the full search & replace
+	for (; *ptr; ++ptr) {
+		if (*ptr == what)
+			*ptr = with;
+	}
+}
+
+void String::Replace(const String &what, const String &with) {
+	if ((what._len == 0) || (_len < what._len) || strcmp(what._cstr, with._cstr) == 0)
+		return;
+
+	const size_t len_src = what._len;
+	const size_t len_dst = with._len;
+	const size_t len_add = Math::Surplus(len_dst, len_src);
+	char *ptr = strstr(_cstr, what._cstr);
+	if (!ptr)
+		return; // pattern not found once, bail out early
+	// Special case for calling BecomeUnique on the first find
+	if (IsShared() && len_add == 0) {
+		ptrdiff_t diff = ptr - _cstr;
+		BecomeUnique(); // if same length make a unique copy once
+		ptr = _cstr + diff; // BecomeUnique will realloc memory
+	}
+	// Do the full search & replace
+	for (; ptr; ptr = strstr(ptr, what._cstr)) {
+		if (len_add > 0) {
+			ptrdiff_t diff = ptr - _cstr;
+			ReserveAndShift(false, len_add);
+			ptr = _cstr + diff; // ReserveAndShift may realloc memory
+		}
+		if (len_src != len_dst)
+			memmove(ptr + len_dst, ptr + len_src, _len - (ptr - _cstr + len_src) + 1);
+		memcpy(ptr, with._cstr, len_dst);
+		_len += len_dst - len_src;
+		ptr += len_dst;
+	}
 }
 
-void String::ReplaceMid(size_t from, size_t count, const char *cstr) {
-	if (!cstr)
-		cstr = "";
-	size_t length = strlen(cstr);
+void String::ReplaceMid(size_t from, size_t count, const String &str) {
+	size_t length = str._len;
 	Math::ClampLength(from, count, (size_t)0, _len);
 	ReserveAndShift(false, Math::Surplus(length, count));
-	memmove(_cstr + from + length, _cstr + from + count, _len - (from + count) + 1);
-	memcpy(_cstr + from, cstr, length);
+	if (count != str._len)
+		memmove(_cstr + from + length, _cstr + from + count, _len - (from + count) + 1);
+	memcpy(_cstr + from, str._cstr, length);
 	_len += length - count;
 }
 
 void String::Reverse() {
 	if (_len <= 1)
-		return;	// nothing to reverse if 1 char or less
+		return; // nothing to reverse if 1 char or less
 	BecomeUnique();
 	for (char *fw = _cstr, *bw = _cstr + _len - 1;
-	        fw < bw; ++fw, --bw) {
+		fw < bw; ++fw, --bw) {
 		SWAP(*fw, *bw);
 	}
 }
 
 void String::SetAt(size_t index, char c) {
-	if (_cstr && index < _len && c) {
+	if ((index < _len) && c) {
 		BecomeUnique();
 		_cstr[index] = c;
 	}
@@ -649,7 +710,7 @@ void String::Trim(char c) {
 }
 
 void String::TrimLeft(char c) {
-	if ((_len == 0) || !_len) {
+	if (_len == 0) {
 		return;
 	}
 
@@ -676,7 +737,7 @@ void String::TrimLeft(char c) {
 }
 
 void String::TrimRight(char c) {
-	if ((_len == 0) || !_len) {
+	if (_len == 0) {
 		return;
 	}
 
@@ -755,7 +816,7 @@ void String::TruncateToRightSection(char separator, bool exclude_separator) {
 }
 
 void String::TruncateToSection(char separator, size_t first, size_t last,
-                               bool exclude_first_sep, bool exclude_last_sep) {
+	bool exclude_first_sep, bool exclude_last_sep) {
 	if ((_len == 0) || !separator) {
 		return;
 	}
@@ -763,7 +824,7 @@ void String::TruncateToSection(char separator, size_t first, size_t last,
 	size_t slice_from;
 	size_t slice_to;
 	if (FindSection(separator, first, last, exclude_first_sep, exclude_last_sep,
-	                slice_from, slice_to)) {
+		slice_from, slice_to)) {
 		TruncateToMid(slice_from, slice_to - slice_from);
 	} else {
 		Empty();
@@ -773,11 +834,10 @@ void String::TruncateToSection(char separator, size_t first, size_t last,
 void String::Wrap(const char *cstr) {
 	Free();
 	_buf = nullptr;
-	// Note that String is NOT supposed to *modify* the const buffer.
-	// Any non-read operation on the buffer is preceded by a call to BecomeUnique,
-	// which in turn will allocate a reference-counted buffer copy.
-	_cstr = const_cast<char *>(cstr);
-	_len = strlen(cstr);
+	// Note that String will NOT *modify* the const buffer.
+	// Any write operation on the buffer is preceded by a call to BecomeUnique.
+	_cstr = const_cast<char *>(cstr ? cstr : "");
+	_len = strlen(_cstr);
 }
 
 String &String::operator=(const String &str) {
@@ -793,6 +853,19 @@ String &String::operator=(const String &str) {
 	return *this;
 }
 
+String &String::operator=(String &&str) {
+	Free();
+	_cstr = str._cstr;
+	_len = str._len;
+	_buf = str._buf;
+	_bufHead = str._bufHead;
+	str._cstr = const_cast<char *>("");
+	str._len = 0;
+	str._buf = nullptr;
+	str._bufHead = nullptr;
+	return *this;
+}
+
 String &String::operator=(const char *cstr) {
 	SetString(cstr);
 	return *this;
@@ -808,10 +881,6 @@ void String::Create(size_t max_length) {
 }
 
 void String::Copy(size_t max_length, size_t offset) {
-	if ((_len == 0)) {
-		return;
-	}
-
 	char *new_data = new char[sizeof(String::BufHeader) + max_length + 1];
 	// remember, that _cstr may point to any address in buffer
 	char *cstr_head = new_data + sizeof(String::BufHeader) + offset;
@@ -857,12 +926,12 @@ void String::ReserveAndShift(bool left, size_t more_length) {
 			// make sure we make use of all of our space
 			const char *cstr_head = _buf + sizeof(String::BufHeader);
 			size_t free_space = left ?
-			                    _cstr - cstr_head :
-			                    (cstr_head + _bufHead->Capacity) - (_cstr + _len);
+				_cstr - cstr_head :
+				(cstr_head + _bufHead->Capacity) - (_cstr + _len);
 			if (free_space < more_length) {
 				Align((left ?
-				       _cstr + (more_length - free_space) :
-				       _cstr - (more_length - free_space)) - cstr_head);
+					_cstr + (more_length - free_space) :
+					_cstr - (more_length - free_space)) - cstr_head);
 			}
 		}
 	} else { // either empty string, or wrapping external char[] - create new buffer
diff --git a/engines/ags/shared/util/string.h b/engines/ags/shared/util/string.h
index a50f678d2a..61aa6de2a7 100644
--- a/engines/ags/shared/util/string.h
+++ b/engines/ags/shared/util/string.h
@@ -59,32 +59,26 @@ class Stream;
 
 class String {
 public:
+	static const size_t npos = (size_t)-1;
+
 	// Standard constructor: intialize empty string
 	String();
 	// Copy constructor
 	String(const String &);
+	// Move constructor
+	String(String &&);
 	// Initialize with C-string
 	String(const char *cstr);
 	// Initialize by copying up to N chars from C-string
 	String(const char *cstr, size_t length);
 	// Initialize by filling N chars with certain value
 	String(char c, size_t count);
-	// Initialize with a ScummVM string
+	// Initialize from a ScummVM string
 	String(const Common::String &s);
 	~String();
 
-	static const size_t npos = (size_t)-1;
-
-	// TODO: get rid of condition in GetCStr! either make it nullable and test for consequences in engine code,
-	// or make sure it points to "" literal when string is not assigned; also check if GetNullableCStr may be removed.
-	// OR do opposite: make helper function that returns non-null cstr explicitly.
-
 	// Get underlying C-string for reading; this method guarantees valid C-string
 	inline const char *GetCStr() const {
-		return _cstr ? _cstr : "";
-	}
-	// Get C-string or nullptr
-	inline const char *GetNullableCStr() const {
 		return _cstr;
 	}
 	// Get character count
@@ -95,9 +89,11 @@ public:
 	inline bool IsEmpty() const {
 		return _len == 0;
 	}
+	// Tells if the string is either empty or has only whitespace characters
+	bool IsNullOrSpace() const;
 
 	// Those getters are for tests only, hence if AGS_PLATFORM_DEBUG
-	#if AGS_PLATFORM_DEBUG
+#if AGS_PLATFORM_TEST
 	inline const char *GetBuffer() const {
 		return _buf;
 	}
@@ -109,7 +105,7 @@ public:
 	inline size_t GetRefCount() const {
 		return _bufHead ? _bufHead->RefCount : 0;
 	}
-	#endif
+#endif
 
 	// Read() method implies that string length is initially unknown.
 	// max_chars parameter determine the buffer size limit.
@@ -133,23 +129,69 @@ public:
 	// String analysis methods
 	//-------------------------------------------------------------------------
 
-	// Compares with given C-string
+	// Compares with given string
+	int     Compare(const String &str) const {
+		return Compare(str._cstr);
+	}
 	int     Compare(const char *cstr) const;
+	int     CompareNoCase(const String &str) const {
+		return CompareNoCase(str._cstr);
+	}
 	int     CompareNoCase(const char *cstr) const;
-	// Compares the leftmost part of this string with given C-string
-	int     CompareLeft(const char *cstr, size_t count = npos) const;
-	int     CompareLeftNoCase(const char *cstr, size_t count = npos) const;
-	// Compares any part of this string with given C-string
-	int     CompareMid(const char *cstr, size_t from, size_t count = npos) const;
-	int     CompareMidNoCase(const char *cstr, size_t from, size_t count = npos) const;
+	// Compares the leftmost part of this string with given string
+	int     CompareLeft(const String &str, size_t count = -1) const {
+		return CompareLeft(str._cstr, count != -1 ? count : str._len);
+	}
+	int     CompareLeft(const char *cstr, size_t count = -1) const;
+	int     CompareLeftNoCase(const String &str, size_t count = -1) const {
+		return CompareLeftNoCase(str._cstr, count != -1 ? count : str._len);
+	}
+	int     CompareLeftNoCase(const char *cstr, size_t count = -1) const;
+	// Compares any part of this string with given string
+	int     CompareMid(const String &str, size_t from, size_t count = -1) const {
+		return CompareMid(str._cstr, from, count != -1 ? count : str._len);
+	}
+	int     CompareMid(const char *cstr, size_t from, size_t count = -1) const;
+	int     CompareMidNoCase(const String &str, size_t from, size_t count = -1) const {
+		return CompareMidNoCase(str._cstr, from, count != -1 ? count : str._len);
+	}
+	int     CompareMidNoCase(const char *cstr, size_t from, size_t count = -1) const;
 	// Compares the rightmost part of this string with given C-string
-	int     CompareRight(const char *cstr, size_t count = npos) const;
-	int     CompareRightNoCase(const char *cstr, size_t count = npos) const;
+	int     CompareRight(const String &str, size_t count = -1) const {
+		return CompareRight(str._cstr, count != -1 ? count : str._len);
+	}
+	int     CompareRight(const char *cstr, size_t count = -1) const;
+	int     CompareRightNoCase(const String &str, size_t count = -1) const {
+		return CompareRightNoCase(str._cstr, count != -1 ? count : str._len);
+	}
+	int     CompareRightNoCase(const char *cstr, size_t count = -1) const;
+	// Convenience aliases for Compare functions
+	inline bool Equals(const String &str) const {
+		return Compare(str) == 0;
+	}
+	inline bool Equals(const char *cstr) const {
+		return Compare(cstr) == 0;
+	}
+	inline bool StartsWith(const String &str) const {
+		return CompareLeft(str) == 0;
+	}
+	inline bool StartsWith(const char *cstr) const {
+		return CompareLeft(cstr) == 0;
+	}
+	inline bool EndsWidth(const String &str) const {
+		return CompareRight(str) == 0;
+	}
+	inline bool EndsWidth(const char *cstr) const {
+		return CompareRight(cstr) == 0;
+	}
 
 	// These functions search for character or substring inside this string
 	// and return the index of the (first) character, or -1 if nothing found.
 	size_t  FindChar(char c, size_t from = 0) const;
-	size_t  FindCharReverse(char c, size_t from = npos) const;
+	size_t  FindCharReverse(char c, size_t from = -1) const;
+	size_t  FindString(const String &str, size_t from = 0) const {
+		return FindString(str._cstr, from);
+	}
 	size_t  FindString(const char *cstr, size_t from = 0) const;
 
 	// Section methods treat string as a sequence of 'fields', separated by
@@ -164,7 +206,7 @@ public:
 	// This also means that there's always at least one section in any string,
 	// even if there are no separating chars.
 	bool    FindSection(char separator, size_t first, size_t last, bool exclude_first_sep, bool exclude_last_sep,
-						size_t &from, size_t &to) const;
+		size_t &from, size_t &to) const;
 
 	// Get Nth character with bounds check (as opposed to subscript operator)
 	inline char GetAt(size_t index) const {
@@ -188,6 +230,8 @@ public:
 	// won't delete it at destruction. Can be used with string literals.
 	static String Wrapper(const char *cstr);
 
+	// TODO: investigate C++11 solution for variadic templates (would that be more convenient here?)
+
 	static String FromFormat(const char *fcstr, ...);
 	static String FromFormatV(const char *fcstr, va_list argptr);
 	// Reads stream until null-terminator or EOS
@@ -203,7 +247,7 @@ public:
 	// Extract N leftmost characters as a new string
 	String  Left(size_t count) const;
 	// Extract up to N characters starting from given index
-	String  Mid(size_t from, size_t count = npos) const;
+	String  Mid(size_t from, size_t count = -1) const;
 	// Extract N rightmost characters
 	String  Right(size_t count) const;
 
@@ -215,7 +259,7 @@ public:
 	String  RightSection(char separator, bool exclude_separator = true) const;
 	// Extract the range of Xth to Yth fields, separated by the given character
 	String  Section(char separator, size_t first, size_t last,
-					bool exclude_first_sep = true, bool exclude_last_sep = true) const;
+		bool exclude_first_sep = true, bool exclude_last_sep = true) const;
 	// Splits the string into segments divided by the instances of a given character,
 	// including empty segments e.g. if separators follow each other;
 	// returns at least one segment (equal to full string if no separator was found)
@@ -234,15 +278,18 @@ public:
 	void    Compact();
 
 	// Append* methods add content at the string's end, increasing its length
-	// Add C-string at string's end
-	void    Append(const char *cstr);
-	// Add single character at string's end
+	// Appends another string to this string
+	void    Append(const String &str);
+	void    Append(const char *cstr) {
+		String str = String::Wrapper(cstr); Append(str);
+	}
+	// Appends a single character
 	void    AppendChar(char c);
 	// Clip* methods decrease the string, removing defined part
 	// Cuts off leftmost N characters
 	void    ClipLeft(size_t count);
 	// Cuts out N characters starting from given index
-	void    ClipMid(size_t from, size_t count = npos);
+	void    ClipMid(size_t from, size_t count = -1);
 	// Cuts off rightmost N characters
 	void    ClipRight(size_t count);
 	// Cuts off leftmost part, separated by the given char; if no separator was
@@ -253,7 +300,7 @@ public:
 	void    ClipRightSection(char separator, bool include_separator = true);
 	// Cuts out the range of Xth to Yth fields separated by the given character
 	void    ClipSection(char separator, size_t first, size_t last,
-						bool include_first_sep = true, bool include_last_sep = true);
+		bool include_first_sep = true, bool include_last_sep = true);
 	// Sets string length to zero
 	void    Empty();
 	// Makes a new string by filling N chars with certain value
@@ -273,26 +320,37 @@ public:
 	// Merges sequences of same characters into one
 	void    MergeSequences(char c = 0);
 	// Prepend* methods add content before the string's head, increasing its length
-	// Add C-string before string's head
-	void    Prepend(const char *cstr);
-	// Add single character before string's head
+	// Prepends another string to this string
+	void    Prepend(const String &str);
+	void    Prepend(const char *cstr) {
+		String str = String::Wrapper(cstr); Prepend(str);
+	}
+	// Prepends a single character
 	void    PrependChar(char c);
 	// Replaces all occurences of one character with another character
 	void    Replace(char what, char with);
+	// Replaces all occurences of one substring with another substring
+	void    Replace(const String &what, const String &with);
+	void    Replace(const char *what, const char *with) {
+		String whats = String::Wrapper(what), withs = String::Wrapper(with); Replace(whats, withs);
+	}
 	// Replaces particular substring with another substring; new substring
 	// may have different length
-	void    ReplaceMid(size_t from, size_t count, const char *cstr);
+	void    ReplaceMid(size_t from, size_t count, const String &str);
+	void    ReplaceMid(size_t from, size_t count, const char *cstr) {
+		String str = String::Wrapper(cstr); ReplaceMid(from, count, str);
+	}
 	// Reverses the string
 	void    Reverse();
 	// Overwrite the Nth character of the string; does not change string's length
 	void    SetAt(size_t index, char c);
 	// Makes a new string by copying up to N chars from C-string
-	void    SetString(const char *cstr, size_t length = npos);
+	void    SetString(const char *cstr, size_t length = -1);
 	// For all Trim functions, if given character value is 0, all whitespace
 	// characters (space, tabs, CRLF) are removed.
 	// Remove heading and trailing characters from the string
 	void    Trim(char c = 0);
-	// Remove heading characters from the string;
+	// Remove heading characters from the string; 
 	void    TrimLeft(char c = 0);
 	// Remove trailing characters from the string
 	void    TrimRight(char c = 0);
@@ -300,7 +358,7 @@ public:
 	// Truncate the string to the leftmost N characters
 	void    TruncateToLeft(size_t count);
 	// Truncate the string to the middle N characters
-	void    TruncateToMid(size_t from, size_t count = npos);
+	void    TruncateToMid(size_t from, size_t count = -1);
 	// Truncate the string to the rightmost N characters
 	void    TruncateToRight(size_t count);
 	// Truncate the string to the leftmost part, separated by the given char;
@@ -312,7 +370,7 @@ public:
 	// Truncate the string to range of Xth to Yth fields separated by the
 	// given character
 	void    TruncateToSection(char separator, size_t first, size_t last,
-							  bool exclude_first_sep = true, bool exclude_last_sep = true);
+		bool exclude_first_sep = true, bool exclude_last_sep = true);
 	// Wraps the given string buffer without owning it, won't count references,
 	// won't delete it at destruction. Can be used with string literals.
 	void    Wrap(const char *cstr);
@@ -322,32 +380,42 @@ public:
 	//-------------------------------------------------------------------------
 
 	inline operator const char *() const {
-		return GetCStr();
+		return _cstr;
 	}
 	// Assign String by sharing data reference
-	String &operator=(const String &);
+	String &operator=(const String &str);
+	// Move operator
+	String &operator=(String &&str);
 	// Assign C-string by copying contents
 	String &operator=(const char *cstr);
 	inline char operator[](size_t index) const {
 		assert(index < _len);
 		return _cstr[index];
 	}
-	inline bool operator==(const char *cstr) const {
+	inline bool operator ==(const String &str) const {
+		return Compare(str) == 0;
+	}
+	inline bool operator ==(const char *cstr) const {
 		return Compare(cstr) == 0;
 	}
-	inline bool operator!=(const char *cstr) const {
+	inline bool operator !=(const String &str) const {
+		return Compare(str) != 0;
+	}
+	inline bool operator !=(const char *cstr) const {
 		return Compare(cstr) != 0;
 	}
+	inline bool operator <(const String &str) const {
+		return Compare(str) < 0;
+	}
 	inline bool operator <(const char *cstr) const {
 		return Compare(cstr) < 0;
 	}
-
 	// Converts an AGS string to a ScummVM one
 	operator Common::String() const {
-		return Common::String(GetNullableCStr());
+		return Common::String(_cstr);
 	}
 
-	private:
+private:
 	// Creates new empty string with buffer enough to fit given length
 	void    Create(size_t buffer_length);
 	// Release string and copy data to the new buffer
@@ -363,8 +431,9 @@ public:
 	// or after the current string data
 	void    ReserveAndShift(bool left, size_t more_length);
 
+	// Internal String data
 	char *_cstr;  // pointer to actual string data; always valid, never null
-	size_t  _len; // valid string length, in characters, excluding null-term
+	size_t  _len;    // valid string length, in characters, excluding null-term
 
 	// Header of a reference-counted buffer
 	struct BufHeader {
diff --git a/engines/ags/shared/util/string_types.h b/engines/ags/shared/util/string_types.h
index ea2ca02fd4..ec491bbe24 100644
--- a/engines/ags/shared/util/string_types.h
+++ b/engines/ags/shared/util/string_types.h
@@ -54,33 +54,33 @@ inline size_t Hash_LowerCase(const char *data, const size_t len) {
 namespace AGS3 {
 
 struct CaseSensitiveString_EqualTo {
-bool operator()(const ::AGS3::AGS::Shared::String &x, const ::AGS3::AGS::Shared::String &y) const {
-	return x.Compare(y) == 0;
-}
+	bool operator()(const ::AGS3::AGS::Shared::String &x, const ::AGS3::AGS::Shared::String &y) const {
+		return x.Compare(y) == 0;
+	}
 };
 
 struct CaseSensitiveString_Hash {
-uint operator()(const ::AGS3::AGS::Shared::String &x) const {
-	return Common::hashit(x.GetNullableCStr());
-}
+	uint operator()(const ::AGS3::AGS::Shared::String &x) const {
+		return Common::hashit(x.GetCStr());
+	}
 };
 
 struct IgnoreCase_EqualTo {
-bool operator()(const ::AGS3::AGS::Shared::String &x, const ::AGS3::AGS::Shared::String &y) const {
-	return x.CompareNoCase(y) == 0;
-}
+	bool operator()(const ::AGS3::AGS::Shared::String &x, const ::AGS3::AGS::Shared::String &y) const {
+		return x.CompareNoCase(y) == 0;
+	}
 };
 
 struct IgnoreCase_Hash {
-uint operator()(const ::AGS3::AGS::Shared::String &x) const {
-	return Common::hashit_lower(x.GetNullableCStr());
-}
+	uint operator()(const ::AGS3::AGS::Shared::String &x) const {
+		return Common::hashit_lower(x.GetCStr());
+	}
 };
 
 struct IgnoreCase_LessThan {
-bool operator()(const ::AGS3::AGS::Shared::String &x, const ::AGS3::AGS::Shared::String &y) const {
-	return x.CompareNoCase(y) < 0;
-}
+	bool operator()(const ::AGS3::AGS::Shared::String &x, const ::AGS3::AGS::Shared::String &y) const {
+		return x.CompareNoCase(y) < 0;
+	}
 };
 
 } // namespace AGS3
@@ -95,9 +95,9 @@ namespace Common {
 // hash anyway.
 template<>
 struct Hash<AGS3::AGS::Shared::String> {
-uint operator()(const AGS3::AGS::Shared::String &s) const {
-	return Common::hashit(s.GetNullableCStr());
-}
+	uint operator()(const AGS3::AGS::Shared::String &s) const {
+		return Common::hashit(s.GetCStr());
+	}
 };
 
 } // namespace Common


Commit: d57474ce5976b1fc885de7d2710f0a069ca5b486
    https://github.com/scummvm/scummvm/commit/d57474ce5976b1fc885de7d2710f0a069ca5b486
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:58-07:00

Commit Message:
AGS: Provided more function variants accepting const String&

>From upstream 44402962003db439e54d79e0c562fba1cf59e455

Changed paths:
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/game.h
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/ac/global_game.h
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/quit.cpp
    engines/ags/shared/ac/common.cpp
    engines/ags/shared/ac/common.h
    engines/ags/shared/ac/sprite_cache.cpp
    engines/ags/shared/ac/sprite_cache.h
    engines/ags/shared/debugging/debug_manager.cpp
    engines/ags/shared/debugging/out.h
    engines/ags/shared/game/room_struct.cpp
    engines/ags/shared/game/room_struct.h
    engines/ags/shared/gfx/allegro_bitmap.h
    engines/ags/shared/gfx/bitmap.h


diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index ca7d5e4742..79b7313cb8 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -289,7 +289,7 @@ bool SetCustomSaveParent(const String &path) {
 	return false;
 }
 
-bool SetSaveGameDirectoryPath(const char *newFolder, bool explicit_path) {
+bool SetSaveGameDirectoryPath(const String &newFolder, bool explicit_path) {
 #if AGS_PLATFORM_SCUMMVM
 	return false;
 #else
@@ -336,7 +336,7 @@ bool SetSaveGameDirectoryPath(const char *newFolder, bool explicit_path) {
 #endif
 }
 
-int Game_SetSaveGameDirectory(const char *newFolder) {
+int Game_SetSaveGameDirectory(const String &newFolder) {
 	return SetSaveGameDirectoryPath(newFolder, false) ? 1 : 0;
 }
 
diff --git a/engines/ags/engine/ac/game.h b/engines/ags/engine/ac/game.h
index 082866ddf3..cc5373fefe 100644
--- a/engines/ags/engine/ac/game.h
+++ b/engines/ags/engine/ac/game.h
@@ -96,8 +96,8 @@ int Game_GetDialogCount();
 bool SetCustomSaveParent(const Shared::String &path);
 // If explicit_path flag is false, the actual path will be constructed
 // as a relative to system's user saves directory
-bool SetSaveGameDirectoryPath(const char *newFolder, bool explicit_path = false);
-int Game_SetSaveGameDirectory(const char *newFolder);
+bool SetSaveGameDirectoryPath(const Shared::String &newFolder, bool explicit_path = false);
+int Game_SetSaveGameDirectory(const Shared::String &newFolder);
 const char *Game_GetSaveSlotDescription(int slnum);
 
 const char *Game_GetGlobalStrings(int index);
diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 56ffb7db1a..a74aabc0ff 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -233,7 +233,7 @@ void GetGlobalString(int index, char *strval) {
 }
 
 // TODO: refactor this method, and use same shared procedure at both normal stop/startup and in RunAGSGame
-int RunAGSGame(const char *newgame, unsigned int mode, int data) {
+int RunAGSGame(const String &newgame, unsigned int mode, int data) {
 
 	can_run_delayed_command();
 
diff --git a/engines/ags/engine/ac/global_game.h b/engines/ags/engine/ac/global_game.h
index 1add95664a..78224eb169 100644
--- a/engines/ags/engine/ac/global_game.h
+++ b/engines/ags/engine/ac/global_game.h
@@ -58,7 +58,7 @@ void SetGlobalInt(int index, int valu);
 int  GetGlobalInt(int index);
 void SetGlobalString(int index, const char *newval);
 void GetGlobalString(int index, char *strval);
-int  RunAGSGame(const char *newgame, unsigned int mode, int data);
+int  RunAGSGame(const Shared::String &newgame, unsigned int mode, int data);
 int  GetGameParameter(int parm, int data1, int data2, int data3);
 void QuitGame(int dialog);
 void SetRestartPoint();
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 725178a47c..f22150db3a 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -207,7 +207,7 @@ static String find_game_data_in_config(const String &path) {
 		Debug::Printf("Found game config: %s", def_cfg_file.GetCStr());
 		Debug::Printf(" Cfg: data file: %s", data_file.GetCStr());
 		// Only accept if it's a relative path
-		if (!data_file.IsEmpty() && is_relative_filename(data_file))
+		if (!data_file.IsEmpty() && Path::IsRelativePath(data_file))
 			return Path::ConcatPaths(path, data_file);
 	}
 	return ""; // not found in config
diff --git a/engines/ags/engine/main/quit.cpp b/engines/ags/engine/main/quit.cpp
index 0eb050264e..ba8f2582f7 100644
--- a/engines/ags/engine/main/quit.cpp
+++ b/engines/ags/engine/main/quit.cpp
@@ -151,12 +151,12 @@ QuitReason quit_check_for_error_state(const char *&qmsg, String &alertis) {
 	}
 }
 
-void quit_message_on_exit(const char *qmsg, String &alertis, QuitReason qreason) {
+void quit_message_on_exit(const String &qmsg, String &alertis, QuitReason qreason) {
 	// successful exit displays no messages (because Windoze closes the dos-box
 	// if it is empty).
 	if ((qreason & kQuitKind_NormalExit) == 0 && !_G(handledErrorInEditor)) {
 		// Display the message (at this point the window still exists)
-		sprintf(_G(pexbuf), "%s\n", qmsg);
+		sprintf(_G(pexbuf), "%s\n", qmsg.GetCStr());
 		alertis.Append(_G(pexbuf));
 		_G(platform)->DisplayAlert("%s", alertis.GetCStr());
 	}
diff --git a/engines/ags/shared/ac/common.cpp b/engines/ags/shared/ac/common.cpp
index 0990898673..6162eebe5b 100644
--- a/engines/ags/shared/ac/common.cpp
+++ b/engines/ags/shared/ac/common.cpp
@@ -29,6 +29,10 @@ using namespace AGS::Shared;
 
 const char *game_file_sig = "Adventure Creator Game File v2";
 
+void quit(const String &str) {
+	quit(str.GetCStr());
+}
+
 void quitprintf(const char *fmt, ...) {
 	va_list ap;
 	va_start(ap, fmt);
diff --git a/engines/ags/shared/ac/common.h b/engines/ags/shared/ac/common.h
index c5b9d77f9e..4fd7bf0259 100644
--- a/engines/ags/shared/ac/common.h
+++ b/engines/ags/shared/ac/common.h
@@ -23,9 +23,12 @@
 #ifndef AGS_SHARED_AC_COMMON_H
 #define AGS_SHARED_AC_COMMON_H
 
+#include "ags/shared/util/string.h"
+
 namespace AGS3 {
 
 // These are the project-dependent functions, they are defined both in Engine.App and AGS.Native.
+void quit(const AGS::Shared::String &str);
 void quit(const char *);
 void quitprintf(const char *fmt, ...);
 void update_polled_stuff_if_runtime();
diff --git a/engines/ags/shared/ac/sprite_cache.cpp b/engines/ags/shared/ac/sprite_cache.cpp
index a1dc04a28e..677883c3e9 100644
--- a/engines/ags/shared/ac/sprite_cache.cpp
+++ b/engines/ags/shared/ac/sprite_cache.cpp
@@ -517,7 +517,7 @@ void SpriteCache::UnCompressSprite(Bitmap *sprite, Stream *in) {
 	}
 }
 
-int SpriteCache::SaveToFile(const char *filename, bool compressOutput, SpriteFileIndex &index) {
+int SpriteCache::SaveToFile(const String &filename, bool compressOutput, SpriteFileIndex &index) {
 	Stream *output = Shared::File::CreateFile(filename);
 	if (output == nullptr)
 		return -1;
@@ -659,7 +659,7 @@ int SpriteCache::SaveToFile(const char *filename, bool compressOutput, SpriteFil
 	return 0;
 }
 
-int SpriteCache::SaveSpriteIndex(const char *filename, const SpriteFileIndex &index) {
+int SpriteCache::SaveSpriteIndex(const String &filename, const SpriteFileIndex &index) {
 	// write the sprite index file
 	Stream *out = File::CreateFile(filename);
 	if (!out)
@@ -682,7 +682,7 @@ int SpriteCache::SaveSpriteIndex(const char *filename, const SpriteFileIndex &in
 	return 0;
 }
 
-HError SpriteCache::InitFile(const char *filename, const char *sprindex_filename) {
+HError SpriteCache::InitFile(const String &filename, const String &sprindex_filename) {
 	SpriteFileVersion vers;
 	char buff[20];
 	soff_t spr_initial_offs = 0;
@@ -789,7 +789,7 @@ HError SpriteCache::RebuildSpriteIndex(AGS::Shared::Stream *in, sprkey_t topmost
 	return HError::None();
 }
 
-bool SpriteCache::LoadSpriteIndexFile(const char *filename, int expectedFileID, soff_t spr_initial_offs, sprkey_t topmost) {
+bool SpriteCache::LoadSpriteIndexFile(const String &filename, int expectedFileID, soff_t spr_initial_offs, sprkey_t topmost) {
 	Stream *fidx = _GP(AssetMgr)->OpenAsset(filename);
 	if (fidx == nullptr) {
 		return false;
@@ -864,7 +864,7 @@ void SpriteCache::DetachFile() {
 	_lastLoad = -2;
 }
 
-int SpriteCache::AttachFile(const char *filename) {
+int SpriteCache::AttachFile(const String &filename) {
 	_stream.reset(_GP(AssetMgr)->OpenAsset(filename));
 	if (_stream == nullptr)
 		return -1;
diff --git a/engines/ags/shared/ac/sprite_cache.h b/engines/ags/shared/ac/sprite_cache.h
index 18ff0b4e4d..67bd74b4d2 100644
--- a/engines/ags/shared/ac/sprite_cache.h
+++ b/engines/ags/shared/ac/sprite_cache.h
@@ -53,6 +53,7 @@ namespace AGS3 {
 
 namespace AGS {
 namespace Shared {
+class String;
 class Stream;
 class Bitmap;
 } // namespace AGS3
@@ -162,18 +163,18 @@ public:
 	void        SetMaxCacheSize(size_t size);
 
 	// Loads sprite reference information and inits sprite stream
-	HAGSError   InitFile(const char *filename, const char *sprindex_filename);
+	HAGSError   InitFile(const Shared::String &filename, const Shared::String &sprindex_filename);
 	// Tells if bitmaps in the file are compressed
 	bool        IsFileCompressed() const;
 	// Opens file stream
-	int         AttachFile(const char *filename);
+	int         AttachFile(const Shared::String &filename);
 	// Closes file stream
 	void        DetachFile();
 	// Saves all sprites to file; fills in index data for external use
 	// TODO: refactor to be able to save main file and index file separately (separate function for gather data?)
-	int         SaveToFile(const char *filename, bool compressOutput, SpriteFileIndex &index);
+	int         SaveToFile(const Shared::String &filename, bool compressOutput, SpriteFileIndex &index);
 	// Saves sprite index table in a separate file
-	int         SaveSpriteIndex(const char *filename, const SpriteFileIndex &index);
+	int         SaveSpriteIndex(const Shared::String &filename, const SpriteFileIndex &index);
 
 	// Loads (if it's not in cache yet) and returns bitmap by the sprite index
 	Shared::Bitmap *operator[](sprkey_t index);
@@ -235,7 +236,7 @@ private:
 	int _listend;
 
 	// Loads sprite index file
-	bool        LoadSpriteIndexFile(const char *filename, int expectedFileID, soff_t spr_initial_offs, sprkey_t topmost);
+	bool        LoadSpriteIndexFile(const Shared::String &filename, int expectedFileID, soff_t spr_initial_offs, sprkey_t topmost);
 	// Rebuilds sprite index from the main sprite file
 	HAGSError   RebuildSpriteIndex(AGS::Shared::Stream *in, sprkey_t topmost, SpriteFileVersion vers);
 	// Writes compressed sprite to the stream
diff --git a/engines/ags/shared/debugging/debug_manager.cpp b/engines/ags/shared/debugging/debug_manager.cpp
index 829578e02a..374e07c2e9 100644
--- a/engines/ags/shared/debugging/debug_manager.cpp
+++ b/engines/ags/shared/debugging/debug_manager.cpp
@@ -197,6 +197,18 @@ void DebugManager::SendMessage(OutputSlot &out, const DebugMessage &msg) {
 
 namespace Debug {
 
+void Printf(const String &text) {
+	_GP(DbgMgr).Print(kDbgGroup_Main, kDbgMsg_Default, text);
+}
+
+void Printf(MessageType mt, const String &text) {
+	_GP(DbgMgr).Print(kDbgGroup_Main, mt, text);
+}
+
+void Printf(DebugGroupID group, MessageType mt, const String &text) {
+	_GP(DbgMgr).Print(group, mt, text);
+}
+
 void Printf(const char *fmt, ...) {
 	va_list argptr;
 	va_start(argptr, fmt);
diff --git a/engines/ags/shared/debugging/out.h b/engines/ags/shared/debugging/out.h
index 05d802c1bb..ae896347e0 100644
--- a/engines/ags/shared/debugging/out.h
+++ b/engines/ags/shared/debugging/out.h
@@ -152,6 +152,12 @@ namespace Debug {
 //
 // Debug output
 //
+// Output a plain message of default group and default type
+void Printf(const String &text);
+// Output a plain message of default group and given type
+void Printf(MessageType mt, const String &text);
+// Output a plain message of given group and type
+void Printf(DebugGroupID group_id, MessageType mt, const String &text);
 // Output formatted message of default group and default type
 void Printf(const char *fmt, ...);
 // Output formatted message of default group and given type
diff --git a/engines/ags/shared/game/room_struct.cpp b/engines/ags/shared/game/room_struct.cpp
index e39d60aba4..32521756bf 100644
--- a/engines/ags/shared/game/room_struct.cpp
+++ b/engines/ags/shared/game/room_struct.cpp
@@ -215,7 +215,7 @@ int RoomStruct::GetRegionTintLuminance(int id) const {
 	return 0;
 }
 
-void load_room(const char *filename, RoomStruct *room, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos) {
+void load_room(const String &filename, RoomStruct *room, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos) {
 	room->Free();
 	room->InitDefaults();
 
@@ -230,7 +230,7 @@ void load_room(const char *filename, RoomStruct *room, bool game_is_hires, const
 			err = UpdateRoomData(room, src.DataVersion, game_is_hires, sprinfos);
 	}
 	if (!err)
-		quitprintf("Unable to load the room file '%s'.\n%s.", filename, err->FullMessage().GetCStr());
+		quitprintf("Unable to load the room file '%s'.\n%s.", filename.GetCStr(), err->FullMessage().GetCStr());
 }
 
 PBitmap FixBitmap(PBitmap bmp, int width, int height) {
diff --git a/engines/ags/shared/game/room_struct.h b/engines/ags/shared/game/room_struct.h
index c9d9e31768..862b795d8f 100644
--- a/engines/ags/shared/game/room_struct.h
+++ b/engines/ags/shared/game/room_struct.h
@@ -52,6 +52,7 @@
 #include "ags/shared/ac/common_defines.h"
 #include "ags/shared/game/interactions.h"
 #include "ags/shared/util/geometry.h"
+#include "ags/shared/util/string.h"
 
 namespace AGS3 {
 
@@ -359,7 +360,7 @@ private:
 
 
 // Loads new room data into the given RoomStruct object
-void load_room(const char *filename, RoomStruct *room, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos);
+void load_room(const String &filename, RoomStruct *room, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos);
 // Checks if it's necessary and upscales low-res room backgrounds and masks for the high resolution game
 // NOTE: it does not upscale object coordinates, because that is usually done when the room is loaded
 void UpscaleRoomBackground(RoomStruct *room, bool game_is_hires);
diff --git a/engines/ags/shared/gfx/allegro_bitmap.h b/engines/ags/shared/gfx/allegro_bitmap.h
index c745420743..cfb63fb246 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.h
+++ b/engines/ags/shared/gfx/allegro_bitmap.h
@@ -36,6 +36,7 @@
 #include "ags/lib/allegro.h" // BITMAP
 #include "ags/shared/core/types.h"
 #include "ags/shared/gfx/bitmap.h"
+#include "ags/shared/util/string.h"
 
 namespace AGS3 {
 namespace AGS {
@@ -64,7 +65,13 @@ public:
 	// Deallocate bitmap
 	void    Destroy();
 
+	bool    LoadFromFile(const String &filename) {
+		return LoadFromFile(filename.GetCStr());
+	}
 	bool    LoadFromFile(const char *filename);
+	bool    SaveToFile(const String &filename, const void *palette) {
+		return SaveToFile(filename.GetCStr(), palette);
+	}
 	bool    SaveToFile(Common::WriteStream &out, const void *palette);
 	bool    SaveToFile(const char *filename, const void *palette);
 
diff --git a/engines/ags/shared/gfx/bitmap.h b/engines/ags/shared/gfx/bitmap.h
index 0bd2f3f2f9..c9875cca2c 100644
--- a/engines/ags/shared/gfx/bitmap.h
+++ b/engines/ags/shared/gfx/bitmap.h
@@ -30,6 +30,7 @@
 #define AGS_SHARED_GFX_BITMAP_H
 
 #include "ags/shared/util/geometry.h"
+#include "ags/shared/util/string.h"
 
 namespace AGS3 {
 namespace AGS {
@@ -70,6 +71,9 @@ Bitmap *CreateTransparentBitmap(int width, int height, int color_depth = 0);
 Bitmap *CreateSubBitmap(Bitmap *src, const Rect &rc);
 Bitmap *CreateBitmapCopy(Bitmap *src, int color_depth = 0);
 Bitmap *LoadFromFile(const char *filename);
+inline Bitmap *LoadFromFile(const String &filename) {
+	return LoadFromFile(filename.GetCStr());
+}
 
 // Stretches bitmap to the requested size. The new bitmap will have same
 // colour depth. Returns original bitmap if no changes are necessary.


Commit: adb44e0336af7a72fdb92fa8175c8938c46156e8
    https://github.com/scummvm/scummvm/commit/adb44e0336af7a72fdb92fa8175c8938c46156e8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:58-07:00

Commit Message:
AGS: Replaced few cases of strcmp with String::Compare and equivs

>From upstream 69288fb93cbc78fc76eb9212e3e23f504b0d50e1

Changed paths:
    engines/ags/engine/ac/button.cpp
    engines/ags/engine/ac/global_audio.cpp
    engines/ags/engine/ac/global_gui.cpp
    engines/ags/engine/ac/label.cpp
    engines/ags/engine/ac/textbox.cpp
    engines/ags/engine/script/script.cpp


diff --git a/engines/ags/engine/ac/button.cpp b/engines/ags/engine/ac/button.cpp
index 88ee082d9d..696ef3bb0d 100644
--- a/engines/ags/engine/ac/button.cpp
+++ b/engines/ags/engine/ac/button.cpp
@@ -93,7 +93,7 @@ void Button_GetText(GUIButton *butt, char *buffer) {
 void Button_SetText(GUIButton *butt, const char *newtx) {
 	newtx = get_translation(newtx);
 
-	if (strcmp(butt->GetText(), newtx)) {
+	if (butt->GetText() != newtx) {
 		butt->SetText(newtx);
 	}
 }
diff --git a/engines/ags/engine/ac/global_audio.cpp b/engines/ags/engine/ac/global_audio.cpp
index 39a1c0dd44..63983acf6b 100644
--- a/engines/ags/engine/ac/global_audio.cpp
+++ b/engines/ags/engine/ac/global_audio.cpp
@@ -602,7 +602,7 @@ bool play_voice_speech(int charid, int sndid) {
 	_G(curLipLine) = -1;  // See if we have voice lip sync for this line
 	_G(curLipLinePhoneme) = -1;
 	for (ii = 0; ii < _G(numLipLines); ii++) {
-		if (ags_stricmp(_G(splipsync)[ii].filename, voice_file) == 0) {
+		if (voice_file.CompareNoCase(_G(splipsync)[ii].filename) == 0) {
 			_G(curLipLine) = ii;
 			break;
 		}
diff --git a/engines/ags/engine/ac/global_gui.cpp b/engines/ags/engine/ac/global_gui.cpp
index 8f1f32e850..b376e4aaeb 100644
--- a/engines/ags/engine/ac/global_gui.cpp
+++ b/engines/ags/engine/ac/global_gui.cpp
@@ -56,7 +56,7 @@ int FindGUIID(const char *GUIName) {
 	for (int ii = 0; ii < _GP(game).numgui; ii++) {
 		if (_GP(guis)[ii].Name.IsEmpty())
 			continue;
-		if (strcmp(_GP(guis)[ii].Name, GUIName) == 0)
+		if (_GP(guis)[ii].Name == GUIName)
 			return ii;
 		if ((_GP(guis)[ii].Name[0u] == 'g') && (ags_stricmp(_GP(guis)[ii].Name.GetCStr() + 1, GUIName) == 0))
 			return ii;
diff --git a/engines/ags/engine/ac/label.cpp b/engines/ags/engine/ac/label.cpp
index 2f269f4457..3c09eefa2a 100644
--- a/engines/ags/engine/ac/label.cpp
+++ b/engines/ags/engine/ac/label.cpp
@@ -46,7 +46,7 @@ void Label_GetText(GUILabel *labl, char *buffer) {
 void Label_SetText(GUILabel *labl, const char *newtx) {
 	newtx = get_translation(newtx);
 
-	if (strcmp(labl->GetText(), newtx)) {
+	if (labl->GetText() != newtx) {
 		labl->SetText(newtx);
 	}
 }
diff --git a/engines/ags/engine/ac/textbox.cpp b/engines/ags/engine/ac/textbox.cpp
index a6f59b4f6c..bf4bdade1a 100644
--- a/engines/ags/engine/ac/textbox.cpp
+++ b/engines/ags/engine/ac/textbox.cpp
@@ -43,7 +43,7 @@ void TextBox_GetText(GUITextBox *texbox, char *buffer) {
 }
 
 void TextBox_SetText(GUITextBox *texbox, const char *newtex) {
-	if (strcmp(texbox->Text, newtex)) {
+	if (texbox->Text != newtex) {
 		texbox->Text = newtex;
 		texbox->NotifyParentChanged();
 	}
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 7be60bcdc3..01e2e57d76 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -594,11 +594,11 @@ InteractionVariable *get_interaction_variable(int varindx) {
 InteractionVariable *FindGraphicalVariable(const char *varName) {
 	int ii;
 	for (ii = 0; ii < _G(numGlobalVars); ii++) {
-		if (ags_stricmp(_G(globalvars)[ii].Name, varName) == 0)
+		if (_G(globalvars)[ii].Name.CompareNoCase(varName) == 0)
 			return &_G(globalvars)[ii];
 	}
 	for (size_t i = 0; i < _GP(thisroom).LocalVariables.size(); ++i) {
-		if (ags_stricmp(_GP(thisroom).LocalVariables[i].Name, varName) == 0)
+		if (_GP(thisroom).LocalVariables[i].Name.CompareNoCase(varName) == 0)
 			return &_GP(thisroom).LocalVariables[i];
 	}
 	return nullptr;


Commit: cd8a0cff0d898bc62aeafd52ca39a713a13323fa
    https://github.com/scummvm/scummvm/commit/cd8a0cff0d898bc62aeafd52ca39a713a13323fa
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:59-07:00

Commit Message:
AGS: Removed unnecessary strlen over String

>From upstream 3947e968ea306cde579936bf02295bf285d7583a

Changed paths:
    engines/ags/engine/ac/dialog.cpp


diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index d952ff4112..0b06bcae26 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -821,9 +821,9 @@ bool DialogOptions::Run() {
 		if (parserInput) {
 			wantRefresh = true;
 			// type into the parser
-			if ((gkey == eAGSKeyCodeF3) || ((gkey == eAGSKeyCodeSpace) && (strlen(parserInput->Text) == 0))) {
+			if ((gkey == eAGSKeyCodeF3) || ((gkey == eAGSKeyCodeSpace) && (parserInput->Text.GetLength() == 0))) {
 				// write previous contents into textbox (F3 or Space when box is empty)
-				for (unsigned int i = strlen(parserInput->Text); i < strlen(_GP(play).lastParserEntry); i++) {
+				for (unsigned int i = parserInput->Text.GetLength(); i < strlen(_GP(play).lastParserEntry); i++) {
 					parserInput->OnKeyPress(_GP(play).lastParserEntry[i]);
 				}
 				//ags_domouse(DOMOUSE_DISABLE);


Commit: eb1e337edd554b82e0131c89693df80b962f0eac
    https://github.com/scummvm/scummvm/commit/eb1e337edd554b82e0131c89693df80b962f0eac
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:08:59-07:00

Commit Message:
AGS: Removed String's "const char*" conversion operator

>From upstream 7c426674e7e53bffe9120f8ffc059b77fa03a606

Changed paths:
    engines/ags/ags.cpp
    engines/ags/engine/ac/button.cpp
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/drawing_surface.cpp
    engines/ags/engine/ac/file.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_drawing_surface.cpp
    engines/ags/engine/ac/global_game.cpp
    engines/ags/engine/ac/global_hotspot.cpp
    engines/ags/engine/ac/global_object.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/ac/hotspot.cpp
    engines/ags/engine/ac/label.cpp
    engines/ags/engine/ac/listbox.cpp
    engines/ags/engine/ac/object.cpp
    engines/ags/engine/ac/parser.cpp
    engines/ags/engine/ac/properties.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/ac/string.cpp
    engines/ags/engine/ac/system.cpp
    engines/ags/engine/ac/textbox.cpp
    engines/ags/engine/debugging/debug.cpp
    engines/ags/engine/debugging/log_file.cpp
    engines/ags/engine/gui/gui_dialog.cpp
    engines/ags/engine/gui/gui_engine.cpp
    engines/ags/engine/gui/my_label.cpp
    engines/ags/engine/main/config.cpp
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/main/quit.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/plugins/ags_plugin.cpp
    engines/ags/shared/ac/game_setup_struct.cpp
    engines/ags/shared/core/asset_manager.cpp
    engines/ags/shared/game/interactions.cpp
    engines/ags/shared/game/room_file.cpp
    engines/ags/shared/gui/gui_button.cpp
    engines/ags/shared/gui/gui_label.cpp
    engines/ags/shared/gui/gui_listbox.cpp
    engines/ags/shared/gui/gui_textbox.cpp
    engines/ags/shared/script/cc_error.cpp
    engines/ags/shared/util/file_stream.cpp
    engines/ags/shared/util/multi_file_lib.cpp
    engines/ags/shared/util/path.cpp
    engines/ags/shared/util/string.h


diff --git a/engines/ags/ags.cpp b/engines/ags/ags.cpp
index 1c945fe290..3423127085 100644
--- a/engines/ags/ags.cpp
+++ b/engines/ags/ags.cpp
@@ -146,7 +146,7 @@ Common::Error AGSEngine::run() {
 		return Common::kUnknownError;
 
 	if (_G(justDisplayVersion)) {
-		_G(platform)->WriteStdOut(AGS3::get_engine_string());
+		_G(platform)->WriteStdOut(AGS3::get_engine_string().GetCStr());
 		return Common::kNoError;
 	}
 
diff --git a/engines/ags/engine/ac/button.cpp b/engines/ags/engine/ac/button.cpp
index 696ef3bb0d..c398618a39 100644
--- a/engines/ags/engine/ac/button.cpp
+++ b/engines/ags/engine/ac/button.cpp
@@ -83,11 +83,11 @@ void Button_Animate(GUIButton *butt, int view, int loop, int speed, int repeat)
 }
 
 const char *Button_GetText_New(GUIButton *butt) {
-	return CreateNewScriptString(butt->GetText());
+	return CreateNewScriptString(butt->GetText().GetCStr());
 }
 
 void Button_GetText(GUIButton *butt, char *buffer) {
-	strcpy(buffer, butt->GetText());
+	strcpy(buffer, butt->GetText().GetCStr());
 }
 
 void Button_SetText(GUIButton *butt, const char *newtx) {
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 0b06bcae26..1c1e730876 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -196,9 +196,9 @@ int run_dialog_script(DialogTopic *dtpp, int dialogID, int offse, int optionInde
 					param1 = _GP(game).playercharacter;
 
 				if (param1 == DCHAR_NARRATOR)
-					Display(get_translation(_G(old_speech_lines)[param2]));
+					Display(get_translation(_G(old_speech_lines)[param2].GetCStr()));
 				else
-					DisplaySpeech(get_translation(_G(old_speech_lines)[param2]), param1);
+					DisplaySpeech(get_translation(_G(old_speech_lines)[param2].GetCStr()), param1);
 
 				_G(said_speech_line) = 1;
 				break;
@@ -346,7 +346,7 @@ int write_dialog_options(Bitmap *ds, bool ds_has_alpha, int dlgxp, int curyp, in
 			wouttext_outline(ds, dlgxp + actualpicwid, curyp, usingfont, text_color, tempbfr);
 		}
 		for (size_t cc = 0; cc < Lines.Count(); cc++) {
-			wouttext_outline(ds, dlgxp + ((cc == 0) ? 0 : 9) + bullet_wid, curyp, usingfont, text_color, Lines[cc]);
+			wouttext_outline(ds, dlgxp + ((cc == 0) ? 0 : 9) + bullet_wid, curyp, usingfont, text_color, Lines[cc].GetCStr());
 			curyp += linespacing;
 		}
 		if (ww < numdisp - 1)
@@ -983,8 +983,8 @@ void DialogOptions::Close() {
 	invalidate_screen();
 
 	if (parserActivated) {
-		strcpy(_GP(play).lastParserEntry, parserInput->Text);
-		ParseText(parserInput->Text);
+		strcpy(_GP(play).lastParserEntry, parserInput->Text.GetCStr());
+		ParseText(parserInput->Text.GetCStr());
 		chose = CHOSE_TEXTPARSER;
 	}
 
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 8ca8413b18..06eacb3836 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -210,11 +210,11 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 				else
 					text_color = text_window_ds->GetCompatibleColor(-asspch);
 
-				wouttext_aligned(text_window_ds, ttxleft, ttyp, oriwid, usingfont, text_color, Lines[ee], _GP(play).text_align);
+				wouttext_aligned(text_window_ds, ttxleft, ttyp, oriwid, usingfont, text_color, Lines[ee].GetCStr(), _GP(play).text_align);
 			} else {
 				text_color = text_window_ds->GetCompatibleColor(asspch);
 				//wouttext_outline(ttxp,ttyp,usingfont,lines[ee]);
-				wouttext_aligned(text_window_ds, ttxleft, ttyp, wii, usingfont, text_color, Lines[ee], _GP(play).speech_text_align);
+				wouttext_aligned(text_window_ds, ttxleft, ttyp, wii, usingfont, text_color, Lines[ee].GetCStr(), _GP(play).speech_text_align);
 			}
 		}
 	} else {
@@ -228,7 +228,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 		adjust_y_coordinate_for_text(&yoffs, usingfont);
 
 		for (size_t ee = 0; ee < Lines.Count(); ee++)
-			wouttext_aligned(text_window_ds, xoffs, yoffs + ee * disp.linespacing, oriwid, usingfont, text_color, Lines[ee], _GP(play).text_align);
+			wouttext_aligned(text_window_ds, xoffs, yoffs + ee * disp.linespacing, oriwid, usingfont, text_color, Lines[ee].GetCStr(), _GP(play).text_align);
 	}
 
 	int ovrtype = OVER_TEXTMSG;
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 6b66ea894d..d235afc530 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -2189,7 +2189,7 @@ void construct_engine_overlay() {
 		_G(debugConsoleBuffer)->FillRect(Rect(0, 0, viewport.GetWidth() - 1, barheight), draw_color);
 		color_t text_color = _G(debugConsoleBuffer)->GetCompatibleColor(16);
 		for (int jj = _G(first_debug_line); jj != _G(last_debug_line); jj = (jj + 1) % DEBUG_CONSOLE_NUMLINES) {
-			wouttextxy(_G(debugConsoleBuffer), 1, ypp, font, text_color, _G(debug_line)[jj]);
+			wouttextxy(_G(debugConsoleBuffer), 1, ypp, font, text_color, _G(debug_line)[jj].GetCStr());
 			ypp += txtspacing;
 		}
 
diff --git a/engines/ags/engine/ac/drawing_surface.cpp b/engines/ags/engine/ac/drawing_surface.cpp
index 3d5c1fe9f6..69c7fc5f42 100644
--- a/engines/ags/engine/ac/drawing_surface.cpp
+++ b/engines/ags/engine/ac/drawing_surface.cpp
@@ -305,12 +305,12 @@ void DrawingSurface_DrawStringWrapped(ScriptDrawingSurface *sds, int xx, int yy,
 		int drawAtX = xx;
 
 		if (alignment & kMAlignHCenter) {
-			drawAtX = xx + ((wid / 2) - wgettextwidth(Lines[i], font) / 2);
+			drawAtX = xx + ((wid / 2) - wgettextwidth(Lines[i].GetCStr(), font) / 2);
 		} else if (alignment & kMAlignRight) {
-			drawAtX = (xx + wid) - wgettextwidth(Lines[i], font);
+			drawAtX = (xx + wid) - wgettextwidth(Lines[i].GetCStr(), font);
 		}
 
-		wouttext_outline(ds, drawAtX, yy + linespacing * i, font, text_color, Lines[i]);
+		wouttext_outline(ds, drawAtX, yy + linespacing * i, font, text_color, Lines[i].GetCStr());
 	}
 
 	sds->FinishedDrawing();
diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index 7862560d84..8625b3f9fd 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -73,10 +73,10 @@ int File_Delete(const char *fnmm) {
 	if (!ResolveScriptPath(fnmm, false, rp))
 		return 0;
 
-	if (::remove(rp.FullPath) == 0)
+	if (::remove(rp.FullPath.GetCStr()) == 0)
 		return 1;
 	if (_G(errnum) == AL_ENOENT && !rp.AltPath.IsEmpty() && rp.AltPath.Compare(rp.FullPath) != 0)
-		return ::remove(rp.AltPath) == 0 ? 1 : 0;
+		return ::remove(rp.AltPath.GetCStr()) == 0 ? 1 : 0;
 	return 0;
 }
 
@@ -307,7 +307,7 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 	debugC(::AGS::kDebugFilePath, "ResolveScriptPath(%s)", orig_sc_path.GetCStr());
 	rp = ResolvedPath();
 
-	bool is_absolute = !is_relative_filename(orig_sc_path);
+	bool is_absolute = !is_relative_filename(orig_sc_path.GetCStr());
 	if (is_absolute && !read_only) {
 		debug_script_warn("Attempt to access file '%s' denied (cannot write to absolute path)", orig_sc_path.GetCStr());
 		return false;
@@ -348,7 +348,7 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 		child_path = sc_path.Mid(GameInstallRootToken.GetLength());
 	} else if (sc_path.CompareLeft(GameSavedgamesDirToken) == 0) {
 		parent_dir = get_save_game_directory();
-		child_path = sc_path.Mid(strlen(GameSavedgamesDirToken));
+		child_path = sc_path.Mid(strlen(GameSavedgamesDirToken.GetCStr()));
 #if AGS_PLATFORM_SCUMMVM
 		// Remap "agsgame.*"
 		const char *agsSavePrefix = "/agssave.";
@@ -522,12 +522,12 @@ bool DoesAssetExistInLib(const AssetPath &path) {
 }
 
 String find_assetlib(const String &filename) {
-	String libname = cbuf_to_string_and_free(ci_find_file(_GP(ResPaths).DataDir, filename));
+	String libname = cbuf_to_string_and_free(ci_find_file(_GP(ResPaths).DataDir.GetCStr(), filename.GetCStr()));
 	if (AssetManager::IsDataFile(libname))
 		return libname;
 	if (Path::ComparePaths(_GP(ResPaths).DataDir, _GP(ResPaths).DataDir2) != 0) {
 		// Hack for running in Debugger
-		libname = cbuf_to_string_and_free(ci_find_file(_GP(ResPaths).DataDir2, filename));
+		libname = cbuf_to_string_and_free(ci_find_file(_GP(ResPaths).DataDir2.GetCStr(), filename.GetCStr()));
 		if (AssetManager::IsDataFile(libname))
 			return libname;
 	}
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 79b7313cb8..edf23b93d5 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -343,7 +343,7 @@ int Game_SetSaveGameDirectory(const String &newFolder) {
 const char *Game_GetSaveSlotDescription(int slnum) {
 	String description;
 	if (read_savedgame_description(get_save_game_path(slnum), description)) {
-		return CreateNewScriptString(description);
+		return CreateNewScriptString(description.GetCStr());
 	}
 	return nullptr;
 }
@@ -635,7 +635,7 @@ void Game_SetIgnoreUserInputAfterTextTimeoutMs(int newValueMs) {
 }
 
 const char *Game_GetFileName() {
-	return CreateNewScriptString(_GP(ResPaths).GamePak.Name);
+	return CreateNewScriptString(_GP(ResPaths).GamePak.Name.GetCStr());
 }
 
 const char *Game_GetName() {
@@ -1069,7 +1069,7 @@ bool try_restore_save(const Shared::String &path, int slot) {
 		if (data_overwritten)
 			quitprintf("%s", error.GetCStr());
 		else
-			Display(error);
+			Display(error.GetCStr());
 		return false;
 	}
 	return true;
@@ -1360,7 +1360,7 @@ void get_message_text(int msnum, char *buffer, char giveErr) {
 	}
 
 	buffer[0] = 0;
-	replace_tokens(get_translation(_GP(thisroom).Messages[msnum]), buffer, maxlen);
+	replace_tokens(get_translation(_GP(thisroom).Messages[msnum].GetCStr()), buffer, maxlen);
 }
 
 bool unserialize_audio_script_object(int index, const char *objectType, const char *serializedData, int dataSize) {
diff --git a/engines/ags/engine/ac/global_drawing_surface.cpp b/engines/ags/engine/ac/global_drawing_surface.cpp
index 043481ab3b..511fb0865f 100644
--- a/engines/ags/engine/ac/global_drawing_surface.cpp
+++ b/engines/ags/engine/ac/global_drawing_surface.cpp
@@ -162,7 +162,7 @@ void RawPrintMessageWrapped(int xx, int yy, int wid, int font, int msgm) {
 	RAW_START();
 	color_t text_color = _GP(play).raw_color;
 	for (size_t i = 0; i < Lines.Count(); i++)
-		wouttext_outline(RAW_SURFACE(), xx, yy + linespacing * i, font, text_color, Lines[i]);
+		wouttext_outline(RAW_SURFACE(), xx, yy + linespacing * i, font, text_color, Lines[i].GetCStr());
 	invalidate_screen();
 	mark_current_background_dirty();
 	RAW_END();
diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index a74aabc0ff..dbbd2fe25e 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -587,7 +587,7 @@ void GetLocationName(int xxx, int yyy, char *tempo) {
 	// on object
 	if (loctype == LOCTYPE_OBJ) {
 		aa = _G(getloctype_index);
-		strcpy(tempo, get_translation(_GP(thisroom).Objects[aa].Name));
+		strcpy(tempo, get_translation(_GP(thisroom).Objects[aa].Name.GetCStr()));
 		// Compatibility: < 3.1.1 games returned space for nameless object
 		// (presumably was a bug, but fixing it affected certain games behavior)
 		if (_G(loaded_game_file_version) < kGameVersion_311 && tempo[0] == 0) {
@@ -600,7 +600,7 @@ void GetLocationName(int xxx, int yyy, char *tempo) {
 		return;
 	}
 	onhs = _G(getloctype_index);
-	if (onhs > 0) strcpy(tempo, get_translation(_GP(thisroom).Hotspots[onhs].Name));
+	if (onhs > 0) strcpy(tempo, get_translation(_GP(thisroom).Hotspots[onhs].Name.GetCStr()));
 	if (_GP(play).get_loc_name_last_time != onhs)
 		GUI::MarkSpecialLabelsForUpdate(kLabelMacro_Overhotspot);
 	_GP(play).get_loc_name_last_time = onhs;
diff --git a/engines/ags/engine/ac/global_hotspot.cpp b/engines/ags/engine/ac/global_hotspot.cpp
index 3f88270938..5836ffa696 100644
--- a/engines/ags/engine/ac/global_hotspot.cpp
+++ b/engines/ags/engine/ac/global_hotspot.cpp
@@ -97,7 +97,7 @@ void GetHotspotName(int hotspot, char *buffer) {
 	if ((hotspot < 0) || (hotspot >= MAX_ROOM_HOTSPOTS))
 		quit("!GetHotspotName: invalid hotspot number");
 
-	strcpy(buffer, get_translation(_GP(thisroom).Hotspots[hotspot].Name));
+	strcpy(buffer, get_translation(_GP(thisroom).Hotspots[hotspot].Name.GetCStr()));
 }
 
 void RunHotspotInteraction(int hotspothere, int mood) {
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 8657eb1caa..7d00eeace5 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -389,7 +389,7 @@ void GetObjectName(int obj, char *buffer) {
 	if (!is_valid_object(obj))
 		quit("!GetObjectName: invalid object number");
 
-	strcpy(buffer, get_translation(_GP(thisroom).Objects[obj].Name));
+	strcpy(buffer, get_translation(_GP(thisroom).Objects[obj].Name.GetCStr()));
 }
 
 void MoveObject(int objj, int xx, int yy, int spp) {
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 5998d151ad..c865aea02b 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -320,7 +320,7 @@ void remove_popup_interface(int ifacenum) {
 void process_interface_click(int ifce, int btn, int mbut) {
 	if (btn < 0) {
 		// click on GUI background
-		QueueScriptFunction(kScInstGame, _GP(guis)[ifce].OnClickHandler, 2,
+		QueueScriptFunction(kScInstGame, _GP(guis)[ifce].OnClickHandler.GetCStr(), 2,
 		                    RuntimeScriptValue().SetDynamicObject(&_G(scrGui)[ifce], &_GP(ccDynamicGUI)),
 		                    RuntimeScriptValue().SetInt32(mbut));
 		return;
@@ -345,14 +345,14 @@ void process_interface_click(int ifce, int btn, int mbut) {
 		// otherwise, run interface_click
 		if ((theObj->GetEventCount() > 0) &&
 		        (!theObj->EventHandlers[0].IsEmpty()) &&
-		        (!_G(gameinst)->GetSymbolAddress(theObj->EventHandlers[0]).IsNull())) {
+		        (!_G(gameinst)->GetSymbolAddress(theObj->EventHandlers[0].GetCStr()).IsNull())) {
 			// control-specific event handler
-			if (strchr(theObj->GetEventArgs(0), ',') != nullptr)
-				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0], 2,
+			if (strchr(theObj->GetEventArgs(0).GetCStr(), ',') != nullptr)
+				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0].GetCStr(), 2,
 				                    RuntimeScriptValue().SetDynamicObject(theObj, &_GP(ccDynamicGUIObject)),
 				                    RuntimeScriptValue().SetInt32(mbut));
 			else
-				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0], 1,
+				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0].GetCStr(), 1,
 				                    RuntimeScriptValue().SetDynamicObject(theObj, &_GP(ccDynamicGUIObject)));
 		} else
 			QueueScriptFunction(kScInstGame, "interface_click", 2,
diff --git a/engines/ags/engine/ac/hotspot.cpp b/engines/ags/engine/ac/hotspot.cpp
index b294d439dc..0526ec2c5b 100644
--- a/engines/ags/engine/ac/hotspot.cpp
+++ b/engines/ags/engine/ac/hotspot.cpp
@@ -95,7 +95,7 @@ void Hotspot_GetName(ScriptHotspot *hss, char *buffer) {
 }
 
 const char *Hotspot_GetName_New(ScriptHotspot *hss) {
-	return CreateNewScriptString(get_translation(_GP(thisroom).Hotspots[hss->id].Name));
+	return CreateNewScriptString(get_translation(_GP(thisroom).Hotspots[hss->id].Name.GetCStr()));
 }
 
 bool Hotspot_IsInteractionAvailable(ScriptHotspot *hhot, int mood) {
diff --git a/engines/ags/engine/ac/label.cpp b/engines/ags/engine/ac/label.cpp
index 3c09eefa2a..25e5c1a04d 100644
--- a/engines/ags/engine/ac/label.cpp
+++ b/engines/ags/engine/ac/label.cpp
@@ -36,11 +36,11 @@ namespace AGS3 {
 // ** LABEL FUNCTIONS
 
 const char *Label_GetText_New(GUILabel *labl) {
-	return CreateNewScriptString(labl->GetText());
+	return CreateNewScriptString(labl->GetText().GetCStr());
 }
 
 void Label_GetText(GUILabel *labl, char *buffer) {
-	strcpy(buffer, labl->GetText());
+	strcpy(buffer, labl->GetText().GetCStr());
 }
 
 void Label_SetText(GUILabel *labl, const char *newtx) {
diff --git a/engines/ags/engine/ac/listbox.cpp b/engines/ags/engine/ac/listbox.cpp
index fc19e2fb2b..8044948d2b 100644
--- a/engines/ags/engine/ac/listbox.cpp
+++ b/engines/ags/engine/ac/listbox.cpp
@@ -151,7 +151,7 @@ int ListBox_GetItemAtLocation(GUIListBox *listbox, int x, int y) {
 char *ListBox_GetItemText(GUIListBox *listbox, int index, char *buffer) {
 	if ((index < 0) || (index >= listbox->ItemCount))
 		quit("!ListBoxGetItemText: invalid item specified");
-	strncpy(buffer, listbox->Items[index], 198);
+	strncpy(buffer, listbox->Items[index].GetCStr(), 198);
 	buffer[199] = 0;
 	return buffer;
 }
@@ -160,14 +160,14 @@ const char *ListBox_GetItems(GUIListBox *listbox, int index) {
 	if ((index < 0) || (index >= listbox->ItemCount))
 		quit("!ListBox.Items: invalid index specified");
 
-	return CreateNewScriptString(listbox->Items[index]);
+	return CreateNewScriptString(listbox->Items[index].GetCStr());
 }
 
 void ListBox_SetItemText(GUIListBox *listbox, int index, const char *newtext) {
 	if ((index < 0) || (index >= listbox->ItemCount))
 		quit("!ListBoxSetItemText: invalid item specified");
 
-	if (strcmp(listbox->Items[index], newtext)) {
+	if (strcmp(listbox->Items[index].GetCStr(), newtext)) {
 		listbox->SetItemText(index, newtext);
 	}
 }
diff --git a/engines/ags/engine/ac/object.cpp b/engines/ags/engine/ac/object.cpp
index 63bd783837..462328332f 100644
--- a/engines/ags/engine/ac/object.cpp
+++ b/engines/ags/engine/ac/object.cpp
@@ -269,7 +269,7 @@ const char *Object_GetName_New(ScriptObject *objj) {
 	if (!is_valid_object(objj->id))
 		quit("!Object.Name: invalid object number");
 
-	return CreateNewScriptString(get_translation(_GP(thisroom).Objects[objj->id].Name));
+	return CreateNewScriptString(get_translation(_GP(thisroom).Objects[objj->id].Name.GetCStr()));
 }
 
 bool Object_IsInteractionAvailable(ScriptObject *oobj, int mood) {
diff --git a/engines/ags/engine/ac/parser.cpp b/engines/ags/engine/ac/parser.cpp
index afce78a0a0..641bde48a0 100644
--- a/engines/ags/engine/ac/parser.cpp
+++ b/engines/ags/engine/ac/parser.cpp
@@ -87,7 +87,7 @@ int find_word_in_dictionary(const char *lookfor) {
 		if ((lastletter == 's') || (lastletter == 'S') || (lastletter == '\'')) {
 			String singular = lookfor;
 			singular.ClipRight(1);
-			return find_word_in_dictionary(singular);
+			return find_word_in_dictionary(singular.GetCStr());
 		}
 	}
 	return -1;
diff --git a/engines/ags/engine/ac/properties.cpp b/engines/ags/engine/ac/properties.cpp
index 68ac456d90..b15d915950 100644
--- a/engines/ags/engine/ac/properties.cpp
+++ b/engines/ags/engine/ac/properties.cpp
@@ -77,7 +77,7 @@ void get_text_property(const StringIMap &st_prop, const StringIMap &rt_prop, con
 		return;
 
 	String val = get_property_value(st_prop, rt_prop, property, desc.DefaultValue);
-	strcpy(bufer, val);
+	strcpy(bufer, val.GetCStr());
 }
 
 const char *get_text_property_dynamic_string(const StringIMap &st_prop, const StringIMap &rt_prop, const char *property) {
@@ -86,7 +86,7 @@ const char *get_text_property_dynamic_string(const StringIMap &st_prop, const St
 		return nullptr;
 
 	String val = get_property_value(st_prop, rt_prop, property, desc.DefaultValue);
-	return CreateNewScriptString(val);
+	return CreateNewScriptString(val.GetCStr());
 }
 
 bool set_int_property(StringIMap &rt_prop, const char *property, int value) {
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 0e448dba73..e4b57e9efb 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -162,7 +162,7 @@ const char *Room_GetMessages(int index) {
 	}
 	char buffer[STD_BUFFER_SIZE];
 	buffer[0] = 0;
-	replace_tokens(get_translation(_GP(thisroom).Messages[index]), buffer, STD_BUFFER_SIZE);
+	replace_tokens(get_translation(_GP(thisroom).Messages[index].GetCStr()), buffer, STD_BUFFER_SIZE);
 	return CreateNewScriptString(buffer);
 }
 
diff --git a/engines/ags/engine/ac/string.cpp b/engines/ags/engine/ac/string.cpp
index 43323c89b2..4eeaefbc04 100644
--- a/engines/ags/engine/ac/string.cpp
+++ b/engines/ags/engine/ac/string.cpp
@@ -253,13 +253,13 @@ size_t break_up_text_into_lines(const char *todis, SplitLines &lines, int wii, i
 	if (_GP(game).options[OPT_RIGHTLEFTWRITE])
 		for (size_t rr = 0; rr < lines.Count(); rr++) {
 			lines[rr].Reverse();
-			line_length = wgettextwidth_compensate(lines[rr], fonnt);
+			line_length = wgettextwidth_compensate(lines[rr].GetCStr(), fonnt);
 			if (line_length > _G(longestline))
 				_G(longestline) = line_length;
 		}
 	else
 		for (size_t rr = 0; rr < lines.Count(); rr++) {
-			line_length = wgettextwidth_compensate(lines[rr], fonnt);
+			line_length = wgettextwidth_compensate(lines[rr].GetCStr(), fonnt);
 			if (line_length > _G(longestline))
 				_G(longestline) = line_length;
 		}
diff --git a/engines/ags/engine/ac/system.cpp b/engines/ags/engine/ac/system.cpp
index 15d3e5df5c..8c7667b3dd 100644
--- a/engines/ags/engine/ac/system.cpp
+++ b/engines/ags/engine/ac/system.cpp
@@ -98,7 +98,7 @@ int System_GetViewportWidth() {
 }
 
 const char *System_GetVersion() {
-	return CreateNewScriptString(_G(EngineVersion).LongString);
+	return CreateNewScriptString(_G(EngineVersion).LongString.GetCStr());
 }
 
 int System_GetHardwareAcceleration() {
diff --git a/engines/ags/engine/ac/textbox.cpp b/engines/ags/engine/ac/textbox.cpp
index bf4bdade1a..b783ef4a75 100644
--- a/engines/ags/engine/ac/textbox.cpp
+++ b/engines/ags/engine/ac/textbox.cpp
@@ -35,11 +35,11 @@ namespace AGS3 {
 // ** TEXT BOX FUNCTIONS
 
 const char *TextBox_GetText_New(GUITextBox *texbox) {
-	return CreateNewScriptString(texbox->Text);
+	return CreateNewScriptString(texbox->Text.GetCStr());
 }
 
 void TextBox_GetText(GUITextBox *texbox, char *buffer) {
-	strcpy(buffer, texbox->Text);
+	strcpy(buffer, texbox->Text.GetCStr());
 }
 
 void TextBox_SetText(GUITextBox *texbox, const char *newtex) {
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 0c6e1adb3c..7e7325d06e 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -498,7 +498,7 @@ void scriptDebugHook(ccInstance *ccinst, int linenum) {
 	if (pluginsWantingDebugHooks > 0) {
 		// a plugin is handling the debugging
 		String scname = GetScriptName(ccinst);
-		pl_run_plugin_debug_hooks(scname, linenum);
+		pl_run_plugin_debug_hooks(scname.GetCStr(), linenum);
 		return;
 	}
 
diff --git a/engines/ags/engine/debugging/log_file.cpp b/engines/ags/engine/debugging/log_file.cpp
index cabf1c2f4d..d6a8984ad2 100644
--- a/engines/ags/engine/debugging/log_file.cpp
+++ b/engines/ags/engine/debugging/log_file.cpp
@@ -48,10 +48,10 @@ void LogFile::PrintMessage(const DebugMessage &msg) {
 	}
 
 	if (!msg.GroupName.IsEmpty()) {
-		_file->Write(msg.GroupName, msg.GroupName.GetLength());
+		_file->Write(msg.GroupName.GetCStr(), msg.GroupName.GetLength());
 		_file->Write(" : ", 3);
 	}
-	_file->Write(msg.Text, msg.Text.GetLength());
+	_file->Write(msg.Text.GetCStr(), msg.Text.GetLength());
 	_file->WriteInt8('\n');
 	// We should flush after every write to the log; this will make writing
 	// bit slower, but will increase the chances that all latest output
diff --git a/engines/ags/engine/gui/gui_dialog.cpp b/engines/ags/engine/gui/gui_dialog.cpp
index 5d2d94e1bd..0c8c0a5e23 100644
--- a/engines/ags/engine/gui/gui_dialog.cpp
+++ b/engines/ags/engine/gui/gui_dialog.cpp
@@ -117,7 +117,7 @@ int loadgamedialog() {
 				else {
 					toret = _G(filenumbers)[cursel];
 					String path = get_save_game_path(toret);
-					strcpy(_G(bufTemp), path);
+					strcpy(_G(bufTemp), path.GetCStr());
 					_G(lpTemp) = &_G(bufTemp)[0];
 				}
 			} else if (mes.id == ctrlcancel) {
@@ -237,7 +237,7 @@ int savegamedialog() {
 
 					toret = highestnum + 1;
 					String path = get_save_game_path(toret);
-					strcpy(_G(bufTemp), path);
+					strcpy(_G(bufTemp), path.GetCStr());
 				} else {
 					toret = _G(filenumbers)[cursell];
 					_G(bufTemp)[0] = 0;
@@ -245,7 +245,7 @@ int savegamedialog() {
 
 				if (_G(bufTemp)[0] == 0) {
 					String path = get_save_game_path(toret);
-					strcpy(_G(bufTemp), path);
+					strcpy(_G(bufTemp), path.GetCStr());
 				}
 
 				_G(lpTemp) = &_G(bufTemp)[0];
diff --git a/engines/ags/engine/gui/gui_engine.cpp b/engines/ags/engine/gui/gui_engine.cpp
index 055f82ad6f..70aa4b487c 100644
--- a/engines/ags/engine/gui/gui_engine.cpp
+++ b/engines/ags/engine/gui/gui_engine.cpp
@@ -119,19 +119,19 @@ void GUIObject::NotifyParentChanged() {
 }
 
 void GUILabel::PrepareTextToDraw() {
-	replace_macro_tokens(Flags & kGUICtrl_Translated ? String(get_translation(Text)) : Text, _textToDraw);
+	replace_macro_tokens((Flags & kGUICtrl_Translated) ? get_translation(Text.GetCStr()) : Text.GetCStr(), _textToDraw);
 }
 
 size_t GUILabel::SplitLinesForDrawing(SplitLines &lines) {
 	// Use the engine's word wrap tool, to have hebrew-style writing and other features
-	return break_up_text_into_lines(_textToDraw, lines, Width, Font);
+	return break_up_text_into_lines(_textToDraw.GetCStr(), lines, Width, Font);
 }
 
 void GUITextBox::DrawTextBoxContents(Bitmap *ds, color_t text_color) {
-	wouttext_outline(ds, X + 1 + get_fixed_pixel_size(1), Y + 1 + get_fixed_pixel_size(1), Font, text_color, Text);
+	wouttext_outline(ds, X + 1 + get_fixed_pixel_size(1), Y + 1 + get_fixed_pixel_size(1), Font, text_color, Text.GetCStr());
 	if (IsGUIEnabled(this)) {
 		// draw a cursor
-		int draw_at_x = wgettextwidth(Text, Font) + X + 3;
+		int draw_at_x = wgettextwidth(Text.GetCStr(), Font) + X + 3;
 		int draw_at_y = Y + 1 + getfontheight(Font);
 		ds->DrawRect(Rect(draw_at_x, draw_at_y, draw_at_x + get_fixed_pixel_size(5), draw_at_y + (get_fixed_pixel_size(1) - 1)), text_color);
 	}
@@ -147,14 +147,14 @@ void GUIListBox::DrawItemsUnfix() {
 
 void GUIListBox::PrepareTextToDraw(const String &text) {
 	if (Flags & kGUICtrl_Translated)
-		_textToDraw = get_translation(text);
+		_textToDraw = get_translation(text.GetCStr());
 	else
 		_textToDraw = text;
 }
 
 void GUIButton::PrepareTextToDraw() {
 	if (Flags & kGUICtrl_Translated)
-		_textToDraw = get_translation(_text);
+		_textToDraw = get_translation(_text.GetCStr());
 	else
 		_textToDraw = _text;
 }
diff --git a/engines/ags/engine/gui/my_label.cpp b/engines/ags/engine/gui/my_label.cpp
index 59f63f630a..d97fa89280 100644
--- a/engines/ags/engine/gui/my_label.cpp
+++ b/engines/ags/engine/gui/my_label.cpp
@@ -50,7 +50,7 @@ void MyLabel::draw(Bitmap *ds) {
 	if (break_up_text_into_lines(teptr, Lines, wid, _G(acdialog_font)) == 0)
 		return;
 	for (size_t ee = 0; ee < Lines.Count(); ee++) {
-		wouttext_outline(ds, x, cyp, _G(acdialog_font), text_color, Lines[ee]);
+		wouttext_outline(ds, x, cyp, _G(acdialog_font), text_color, Lines[ee].GetCStr());
 		cyp += TEXT_HT;
 	}
 }
diff --git a/engines/ags/engine/main/config.cpp b/engines/ags/engine/main/config.cpp
index 1be9e9323a..933656b381 100644
--- a/engines/ags/engine/main/config.cpp
+++ b/engines/ags/engine/main/config.cpp
@@ -69,7 +69,7 @@ int INIreadint(const ConfigTree &cfg, const String &sectn, const String &item, i
 	if (!INIreaditem(cfg, sectn, item, str))
 		return def_value;
 
-	return atoi(str);
+	return atoi(str.GetCStr());
 }
 
 float INIreadfloat(const ConfigTree &cfg, const String &sectn, const String &item, float def_value) {
@@ -77,7 +77,7 @@ float INIreadfloat(const ConfigTree &cfg, const String &sectn, const String &ite
 	if (!INIreaditem(cfg, sectn, item, str))
 		return def_value;
 
-	return atof(str);
+	return atof(str.GetCStr());
 }
 
 String INIreadstring(const ConfigTree &cfg, const String &sectn, const String &item, const String &def_value) {
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index f22150db3a..c67dd79078 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -854,7 +854,7 @@ void engine_init_game_settings() {
 
 void engine_setup_scsystem_auxiliary() {
 	// ScriptSystem::aci_version is only 10 chars long
-	strncpy(_GP(scsystem).aci_version, _G(EngineVersion).LongString, 10);
+	strncpy(_GP(scsystem).aci_version, _G(EngineVersion).LongString.GetCStr(), 10);
 	if (_GP(usetup).override_script_os >= 0) {
 		_GP(scsystem).os = _GP(usetup).override_script_os;
 	} else {
diff --git a/engines/ags/engine/main/quit.cpp b/engines/ags/engine/main/quit.cpp
index ba8f2582f7..8174a232af 100644
--- a/engines/ags/engine/main/quit.cpp
+++ b/engines/ags/engine/main/quit.cpp
@@ -59,7 +59,7 @@ using namespace AGS::Engine;
 void quit_tell_editor_debugger(const String &qmsg, QuitReason qreason) {
 	if (_G(editor_debugging_initialized)) {
 		if (qreason & kQuitKind_GameException)
-			_G(handledErrorInEditor) = send_exception_to_editor(qmsg);
+			_G(handledErrorInEditor) = send_exception_to_editor(qmsg.GetCStr());
 		send_message_to_editor("EXIT");
 		_G(editor_debugger)->Shutdown();
 	}
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 01e2e57d76..c38bf9a77f 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -183,10 +183,10 @@ int run_interaction_script(InteractionScripts *nint, int evnt, int chkAny, int i
 
 	if ((strstr(_G(evblockbasename), "character") != nullptr) || (strstr(_G(evblockbasename), "inventory") != nullptr)) {
 		// Character or Inventory (global script)
-		QueueScriptFunction(kScInstGame, nint->ScriptFuncNames[evnt]);
+		QueueScriptFunction(kScInstGame, nint->ScriptFuncNames[evnt].GetCStr());
 	} else {
 		// Other (room script)
-		QueueScriptFunction(kScInstRoom, nint->ScriptFuncNames[evnt]);
+		QueueScriptFunction(kScInstRoom, nint->ScriptFuncNames[evnt].GetCStr());
 	}
 
 	int retval = 0;
@@ -548,7 +548,7 @@ void post_script_cleanup() {
 	for (jj = 0; jj < copyof.numanother; jj++) {
 		old_room_number = _G(displayed_room);
 		QueuedScript &script = copyof.ScFnQueue[jj];
-		RunScriptFunction(script.Instance, script.FnName, script.ParamCount, script.Param1, script.Param2);
+		RunScriptFunction(script.Instance, script.FnName.GetCStr(), script.ParamCount, script.Param1, script.Param2);
 		if (script.Instance == kScInstRoom && script.ParamCount == 1) {
 			// some bogus hack for "on_call" event handler
 			_GP(play).roomscript_finished = 1;
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 4c2fd5c6f8..f36aaac42d 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -316,7 +316,7 @@ void IAGSEngine::DrawTextWrapped(int32 xx, int32 yy, int32 wid, int32 font, int3
 	color_t text_color = ds->GetCompatibleColor(color);
 	data_to_game_coords((int *)&xx, (int *)&yy); // stupid! quick tweak
 	for (size_t i = 0; i < Lines.Count(); i++)
-		draw_and_invalidate_text(ds, xx, yy + linespacing * i, font, text_color, Lines[i]);
+		draw_and_invalidate_text(ds, xx, yy + linespacing * i, font, text_color, Lines[i].GetCStr());
 }
 
 Bitmap glVirtualScreenWrap;
diff --git a/engines/ags/shared/ac/game_setup_struct.cpp b/engines/ags/shared/ac/game_setup_struct.cpp
index 4941f89cfb..7d85cfd938 100644
--- a/engines/ags/shared/ac/game_setup_struct.cpp
+++ b/engines/ags/shared/ac/game_setup_struct.cpp
@@ -335,7 +335,7 @@ void GameSetupStruct::read_room_names(Stream *in, GameDataVersion data_ver) {
 			roomNumbers[bb] = in->ReadInt32();
 			pexbuf.Read(in, STD_BUFFER_SIZE);
 			roomNames[bb] = new char[pexbuf.GetLength() + 1];
-			strcpy(roomNames[bb], pexbuf);
+			strcpy(roomNames[bb], pexbuf.GetCStr());
 		}
 	} else {
 		roomCount = 0;
diff --git a/engines/ags/shared/core/asset_manager.cpp b/engines/ags/shared/core/asset_manager.cpp
index cd622bab74..77cdd0b014 100644
--- a/engines/ags/shared/core/asset_manager.cpp
+++ b/engines/ags/shared/core/asset_manager.cpp
@@ -61,7 +61,7 @@ bool AssetManager::LibsByPriority::operator()(const AssetLibInfo *lib1, const As
 
 
 /* static */ bool AssetManager::IsDataFile(const String &data_file) {
-	Stream *in = ci_fopen(data_file, Shared::kFile_Open, Shared::kFile_Read);
+	Stream *in = ci_fopen(data_file.GetCStr(), Shared::kFile_Open, Shared::kFile_Read);
 	if (in) {
 		MFLUtil::MFLError err = MFLUtil::TestIsMFL(in, true);
 		delete in;
@@ -71,7 +71,7 @@ bool AssetManager::LibsByPriority::operator()(const AssetLibInfo *lib1, const As
 }
 
 /* static */ AssetError AssetManager::ReadDataFileTOC(const String &data_file, AssetLibInfo &lib) {
-	Stream *in = ci_fopen(data_file, Shared::kFile_Open, Shared::kFile_Read);
+	Stream *in = ci_fopen(data_file.GetCStr(), Shared::kFile_Open, Shared::kFile_Read);
 	if (in) {
 		MFLUtil::MFLError err = MFLUtil::ReadHeader(lib, in);
 		delete in;
@@ -178,7 +178,7 @@ AssetError AssetManager::RegisterAssetLib(const String &path, AssetLibEx *&out_l
 	}
 	// ...else try open a data library
 	else {
-		Stream *in = ci_fopen(path, Shared::kFile_Open, Shared::kFile_Read);
+		Stream *in = ci_fopen(path.GetCStr(), Shared::kFile_Open, Shared::kFile_Read);
 		if (!in)
 			return kAssetErrNoLibFile; // can't be opened, return error code
 
@@ -234,7 +234,7 @@ bool AssetManager::GetAssetFromLib(const AssetLibInfo *lib, const String &asset_
 	if (asset == nullptr)
 		return false;
 
-	String libfile = cbuf_to_string_and_free(ci_find_file(lib->BaseDir, lib->LibFileNames[asset->LibUid]));
+	String libfile = cbuf_to_string_and_free(ci_find_file(lib->BaseDir.GetCStr(), lib->LibFileNames[asset->LibUid].GetCStr()));
 	if (libfile.IsEmpty())
 		return false;
 	if (loc) {
@@ -247,7 +247,7 @@ bool AssetManager::GetAssetFromLib(const AssetLibInfo *lib, const String &asset_
 
 bool AssetManager::GetAssetFromDir(const AssetLibInfo *lib, const String &file_name,
                                    AssetLocation *loc, FileOpenMode open_mode, FileWorkMode work_mode) const {
-	String found_file = cbuf_to_string_and_free(ci_find_file(lib->BaseDir, file_name));
+	String found_file = cbuf_to_string_and_free(ci_find_file(lib->BaseDir.GetCStr(), file_name.GetCStr()));
 	if (found_file.IsEmpty() || !Path::IsFile(found_file))
 		return false; // not found, or not a file
 
diff --git a/engines/ags/shared/game/interactions.cpp b/engines/ags/shared/game/interactions.cpp
index e031801a17..50b6bb9ce2 100644
--- a/engines/ags/shared/game/interactions.cpp
+++ b/engines/ags/shared/game/interactions.cpp
@@ -349,7 +349,7 @@ void InteractionVariable::Read(Stream *in) {
 }
 
 void InteractionVariable::Write(Shared::Stream *out) const {
-	out->Write(Name, INTER_VAR_NAME_LENGTH);
+	out->Write(Name.GetCStr(), INTER_VAR_NAME_LENGTH);
 	out->WriteInt8(Type);
 	out->WriteInt32(Value);
 }
diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index c57abfd9b9..36cdb4c61c 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -893,7 +893,7 @@ void WriteMainBlock(const RoomStruct *room, Stream *out) {
 		out->WriteInt8(room->MessageInfos[i].Flags);
 	}
 	for (size_t i = 0; i < room->MessageCount; ++i)
-		write_string_encrypt(out, room->Messages[i]);
+		write_string_encrypt(out, room->Messages[i].GetCStr());
 
 	out->WriteInt16(0); // legacy room animations
 
diff --git a/engines/ags/shared/gui/gui_button.cpp b/engines/ags/shared/gui/gui_button.cpp
index 4d5d8e636a..b6bea54f73 100644
--- a/engines/ags/shared/gui/gui_button.cpp
+++ b/engines/ags/shared/gui/gui_button.cpp
@@ -322,7 +322,7 @@ void GUIButton::DrawText(Bitmap *ds, bool draw_disabled) {
 	color_t text_color = ds->GetCompatibleColor(TextColor);
 	if (draw_disabled)
 		text_color = ds->GetCompatibleColor(8);
-	GUI::DrawTextAligned(ds, _textToDraw, Font, text_color, frame, TextAlignment);
+	GUI::DrawTextAligned(ds, _textToDraw.GetCStr(), Font, text_color, frame, TextAlignment);
 }
 
 void GUIButton::DrawTextButton(Bitmap *ds, bool draw_disabled) {
diff --git a/engines/ags/shared/gui/gui_label.cpp b/engines/ags/shared/gui/gui_label.cpp
index 63b65e395f..a7788e358e 100644
--- a/engines/ags/shared/gui/gui_label.cpp
+++ b/engines/ags/shared/gui/gui_label.cpp
@@ -66,7 +66,7 @@ void GUILabel::Draw(Shared::Bitmap *ds) {
 	for (size_t i = 0;
 	        i < Lines.Count() && (!limit_by_label_frame || at_y <= Y + Height);
 	        ++i, at_y += linespacing) {
-		GUI::DrawTextAlignedHor(ds, Lines[i], Font, text_color, X, X + Width - 1, at_y,
+		GUI::DrawTextAlignedHor(ds, Lines[i].GetCStr(), Font, text_color, X, X + Width - 1, at_y,
 		                        (FrameAlignment)TextAlignment);
 	}
 }
diff --git a/engines/ags/shared/gui/gui_listbox.cpp b/engines/ags/shared/gui/gui_listbox.cpp
index ab70c7acb9..400dccb6c7 100644
--- a/engines/ags/shared/gui/gui_listbox.cpp
+++ b/engines/ags/shared/gui/gui_listbox.cpp
@@ -159,7 +159,7 @@ void GUIListBox::Draw(Shared::Bitmap *ds) {
 		int item_index = item + TopItem;
 		PrepareTextToDraw(Items[item_index]);
 
-		GUI::DrawTextAlignedHor(ds, _textToDraw, Font, text_color, X + 1 + pixel_size, right_hand_edge, at_y + 1,
+		GUI::DrawTextAlignedHor(ds, _textToDraw.GetCStr(), Font, text_color, X + 1 + pixel_size, right_hand_edge, at_y + 1,
 		                        (FrameAlignment)TextAlignment);
 	}
 
diff --git a/engines/ags/shared/gui/gui_textbox.cpp b/engines/ags/shared/gui/gui_textbox.cpp
index cc20d95fdb..b2e606d81d 100644
--- a/engines/ags/shared/gui/gui_textbox.cpp
+++ b/engines/ags/shared/gui/gui_textbox.cpp
@@ -80,7 +80,7 @@ void GUITextBox::OnKeyPress(int keycode) {
 
 	Text.AppendChar(keycode);
 	// if the new string is too long, remove the new character
-	if (wgettextwidth(Text, Font) > (Width - (6 + get_fixed_pixel_size(5))))
+	if (wgettextwidth(Text.GetCStr(), Font) > (Width - (6 + get_fixed_pixel_size(5))))
 		Text.ClipRight(1);
 }
 
diff --git a/engines/ags/shared/script/cc_error.cpp b/engines/ags/shared/script/cc_error.cpp
index c44258ce2c..f9602536a4 100644
--- a/engines/ags/shared/script/cc_error.cpp
+++ b/engines/ags/shared/script/cc_error.cpp
@@ -48,11 +48,11 @@ void cc_error(const char *descr, ...) {
 
 	if (_G(currentline) > 0) {
 		// [IKM] Implementation is project-specific
-		std::pair<String, String> errinfo = cc_error_at_line(displbuf);
+		std::pair<String, String> errinfo = cc_error_at_line(displbuf.GetCStr());
 		_G(ccErrorString) = errinfo.first;
 		_G(ccErrorCallStack) = errinfo.second;
 	} else {
-		_G(ccErrorString) = cc_error_without_line(displbuf);
+		_G(ccErrorString) = cc_error_without_line(displbuf.GetCStr());
 		_G(ccErrorCallStack) = "";
 	}
 
diff --git a/engines/ags/shared/util/file_stream.cpp b/engines/ags/shared/util/file_stream.cpp
index 2d8d41f1a1..ff405e3017 100644
--- a/engines/ags/shared/util/file_stream.cpp
+++ b/engines/ags/shared/util/file_stream.cpp
@@ -194,7 +194,7 @@ void FileStream::Open(const String &file_name, FileOpenMode open_mode, FileWorkM
 
 		if (!file_name.CompareLeftNoCase(SAVE_FOLDER_PREFIX)) {
 			_outSave = g_system->getSavefileManager()->openForSaving(
-			               file_name + strlen(SAVE_FOLDER_PREFIX), false);
+			               file_name.GetCStr() + strlen(SAVE_FOLDER_PREFIX), false);
 		} else {
 			Common::String fname = file_name;
 			if (fname.hasPrefix("./"))
diff --git a/engines/ags/shared/util/multi_file_lib.cpp b/engines/ags/shared/util/multi_file_lib.cpp
index 911c14fdb7..629670a419 100644
--- a/engines/ags/shared/util/multi_file_lib.cpp
+++ b/engines/ags/shared/util/multi_file_lib.cpp
@@ -328,7 +328,7 @@ MFLUtil::MFLError MFLUtil::ReadV30(AssetLibInfo &lib, Stream *in, MFLVersion /*
 }
 
 void MFLUtil::WriteHeader(const AssetLibInfo &lib, MFLVersion lib_version, int lib_index, Stream *out) {
-	out->Write(MFLUtil::HeadSig, MFLUtil::HeadSig.GetLength());
+	out->Write(MFLUtil::HeadSig.GetCStr(), MFLUtil::HeadSig.GetLength());
 	out->WriteByte(lib_version);
 	out->WriteByte(lib_index);   // file number
 
@@ -361,7 +361,7 @@ void MFLUtil::WriteEnder(soff_t lib_offset, MFLVersion lib_index, Stream *out) {
 		out->WriteInt32((int32_t)lib_offset);
 	else
 		out->WriteInt64(lib_offset);
-	out->Write(TailSig, TailSig.GetLength());
+	out->Write(TailSig.GetCStr(), TailSig.GetLength());
 }
 
 void MFLUtil::DecryptText(char *text) {
diff --git a/engines/ags/shared/util/path.cpp b/engines/ags/shared/util/path.cpp
index 75493a733b..56b894ea5c 100644
--- a/engines/ags/shared/util/path.cpp
+++ b/engines/ags/shared/util/path.cpp
@@ -71,11 +71,11 @@ bool IsFileOrDir(const String &filename) {
 }
 
 String GetFilename(const String &path) {
-	return get_filename(path);
+	return get_filename(path.GetCStr());
 }
 
 String GetFileExtension(const String &path) {
-	return get_extension(path);
+	return get_extension(path.GetCStr());
 }
 
 int ComparePaths(const String &path1, const String &path2) {
@@ -120,8 +120,8 @@ bool IsSameOrSubDir(const String &parent, const String &path) {
 	char can_path[MAX_PATH];
 	char relative[MAX_PATH];
 	// canonicalize_filename treats "." as "./." (file in working dir)
-	const char *use_parent = parent == "." ? "./" : parent;
-	const char *use_path = path == "." ? "./" : path;
+	const char *use_parent = parent == "." ? "./" : parent.GetCStr();
+	const char *use_path = path == "." ? "./" : path.GetCStr();
 	canonicalize_filename(can_parent, use_parent, MAX_PATH);
 	canonicalize_filename(can_path, use_path, MAX_PATH);
 	const char *pstr = make_relative_filename(relative, can_parent, can_path, MAX_PATH);
@@ -136,7 +136,7 @@ bool IsSameOrSubDir(const String &parent, const String &path) {
 }
 
 bool IsRelativePath(const String &path) {
-	return is_relative_filename(path);
+	return is_relative_filename(path.GetCStr()) != 0;
 }
 
 void FixupPath(String &path) {
@@ -185,7 +185,7 @@ String MakeAbsolutePath(const String &path) {
 	//}
 #endif
 	char buf[MAX_PATH];
-	canonicalize_filename(buf, abs_path, MAX_PATH);
+	canonicalize_filename(buf, abs_path.GetCStr(), MAX_PATH);
 	abs_path = buf;
 	FixupPath(abs_path);
 	return abs_path;
@@ -196,8 +196,8 @@ String MakeRelativePath(const String &base, const String &path) {
 	char can_path[MAX_PATH];
 	char relative[MAX_PATH];
 	// canonicalize_filename treats "." as "./." (file in working dir)
-	const char *use_parent = base == "." ? "./" : base;
-	const char *use_path = path == "." ? "./" : path; // FIXME?
+	const char *use_parent = base == "." ? "./" : base.GetCStr();
+	const char *use_path = path == "." ? "./" : path.GetCStr(); // FIXME?
 	canonicalize_filename(can_parent, use_parent, MAX_PATH);
 	canonicalize_filename(can_path, use_path, MAX_PATH);
 	String rel_path = make_relative_filename(relative, can_parent, can_path, MAX_PATH);
@@ -249,7 +249,7 @@ String FixupSharedFilename(const String &filename) {
 String GetPathInASCII(const String &path) {
 #if AGS_PLATFORM_OS_WINDOWS
 	char ascii_buffer[MAX_PATH];
-	if (GetShortPathNameA(path, ascii_buffer, MAX_PATH) == 0)
+	if (GetShortPathNameA(path.GetCStr(), ascii_buffer, MAX_PATH) == 0)
 		return "";
 	return ascii_buffer;
 #else
diff --git a/engines/ags/shared/util/string.h b/engines/ags/shared/util/string.h
index 61aa6de2a7..e784e5d2e8 100644
--- a/engines/ags/shared/util/string.h
+++ b/engines/ags/shared/util/string.h
@@ -140,29 +140,29 @@ public:
 	int     CompareNoCase(const char *cstr) const;
 	// Compares the leftmost part of this string with given string
 	int     CompareLeft(const String &str, size_t count = -1) const {
-		return CompareLeft(str._cstr, count != -1 ? count : str._len);
+		return CompareLeft(str._cstr, count != npos ? count : str._len);
 	}
 	int     CompareLeft(const char *cstr, size_t count = -1) const;
 	int     CompareLeftNoCase(const String &str, size_t count = -1) const {
-		return CompareLeftNoCase(str._cstr, count != -1 ? count : str._len);
+		return CompareLeftNoCase(str._cstr, count != npos ? count : str._len);
 	}
 	int     CompareLeftNoCase(const char *cstr, size_t count = -1) const;
 	// Compares any part of this string with given string
 	int     CompareMid(const String &str, size_t from, size_t count = -1) const {
-		return CompareMid(str._cstr, from, count != -1 ? count : str._len);
+		return CompareMid(str._cstr, from, count != npos ? count : str._len);
 	}
 	int     CompareMid(const char *cstr, size_t from, size_t count = -1) const;
 	int     CompareMidNoCase(const String &str, size_t from, size_t count = -1) const {
-		return CompareMidNoCase(str._cstr, from, count != -1 ? count : str._len);
+		return CompareMidNoCase(str._cstr, from, count != npos ? count : str._len);
 	}
 	int     CompareMidNoCase(const char *cstr, size_t from, size_t count = -1) const;
 	// Compares the rightmost part of this string with given C-string
 	int     CompareRight(const String &str, size_t count = -1) const {
-		return CompareRight(str._cstr, count != -1 ? count : str._len);
+		return CompareRight(str._cstr, count != npos ? count : str._len);
 	}
 	int     CompareRight(const char *cstr, size_t count = -1) const;
 	int     CompareRightNoCase(const String &str, size_t count = -1) const {
-		return CompareRightNoCase(str._cstr, count != -1 ? count : str._len);
+		return CompareRightNoCase(str._cstr, count != npos ? count : str._len);
 	}
 	int     CompareRightNoCase(const char *cstr, size_t count = -1) const;
 	// Convenience aliases for Compare functions
@@ -379,9 +379,6 @@ public:
 	// Operators
 	//-------------------------------------------------------------------------
 
-	inline operator const char *() const {
-		return _cstr;
-	}
 	// Assign String by sharing data reference
 	String &operator=(const String &str);
 	// Move operator
@@ -414,6 +411,10 @@ public:
 	operator Common::String() const {
 		return Common::String(_cstr);
 	}
+	// Fixes compilation error in script_set
+	operator bool() const {
+		return !IsEmpty();
+	}
 
 private:
 	// Creates new empty string with buffer enough to fit given length


Commit: 73347d4559482b590c4d999255fb82fb0824de83
    https://github.com/scummvm/scummvm/commit/73347d4559482b590c4d999255fb82fb0824de83
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:00-07:00

Commit Message:
AGS: Remove _G macros from comments

Changed paths:
    engines/ags/engine/ac/character.cpp
    engines/ags/engine/ac/display.cpp
    engines/ags/engine/ac/draw.cpp
    engines/ags/engine/ac/draw.h
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/global_api.cpp
    engines/ags/engine/ac/global_display.cpp
    engines/ags/engine/ac/inventory_item.cpp
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/plugins/ags_plugin.cpp
    engines/ags/plugins/plugin_object_reader.cpp
    engines/ags/plugins/plugin_object_reader.h


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index e089f95dc6..1ce22447ce 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -2069,7 +2069,7 @@ void CheckViewFrameForCharacter(CharacterInfo *chi) {
 Bitmap *GetCharacterImage(int charid, int *isFlipped) {
 	if (!_G(gfxDriver)->HasAcceleratedTransform()) {
 		if (_G(actsps)[charid + MAX_ROOM_OBJECTS] != nullptr) {
-			// the _G(actsps) image is pre-flipped, so no longer register the image as such
+			// the actsps image is pre-flipped, so no longer register the image as such
 			if (isFlipped)
 				*isFlipped = 0;
 			return _G(actsps)[charid + MAX_ROOM_OBJECTS];
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 06eacb3836..aa753e78be 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -116,7 +116,7 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 	}
 
 	if (asspch > 0) {
-		// update the _G(all_buttons_disabled) variable in advance
+		// update the all_buttons_disabled variable in advance
 		// of the adjust_x/y_for_guis calls
 		_GP(play).disabled_user_interface++;
 		update_gui_disabled_status();
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index d235afc530..144ef3b091 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -151,7 +151,7 @@ Bitmap *convert_32_to_32bgr(Bitmap *tempbl) {
 // could copy them to texture without additional changes.
 // AGS own OpenGL renderer tries to sync its behavior with the former one.
 //
-// TODO: make _G(gfxDriver)->GetCompatibleBitmapFormat describe all necessary
+// TODO: make gfxDriver->GetCompatibleBitmapFormat describe all necessary
 // conversions, so that we did not have to guess.
 //
 Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
@@ -1067,7 +1067,7 @@ void get_local_tint(int xpp, int ypp, int nolight,
 
 
 
-// Applies the specified RGB Tint or Light Level to the _G(actsps)
+// Applies the specified RGB Tint or Light Level to the actsps
 // sprite indexed with actspsindex
 void apply_tint_or_light(int actspsindex, int light_level,
                          int tint_amount, int tint_red, int tint_green,
@@ -1133,9 +1133,9 @@ void apply_tint_or_light(int actspsindex, int light_level,
 
 }
 
-// Draws the specified 'sppic' sprite onto _G(actsps)[useindx] at the
+// Draws the specified 'sppic' sprite onto actsps[useindx] at the
 // specified width and height, and flips the sprite if necessary.
-// Returns 1 if something was drawn to _G(actsps); returns 0 if no
+// Returns 1 if something was drawn to actsps; returns 0 if no
 // scaling or stretching was required, in which case nothing was done
 int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
                           int sppic, int newwidth, int newheight,
@@ -1152,7 +1152,7 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 
 		_G(our_eip) = 334;
 
-		// Ensure that anti-aliasing routines have a _G(palette) to
+		// Ensure that anti-aliasing routines have a palette to
 		// use for mapping while faded out
 		if (_G(in_new_room))
 			select_palette(_G(palette));
@@ -1213,8 +1213,8 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
 
 
 
-// create the _G(actsps)[aa] image with the object drawn correctly
-// returns 1 if nothing at all has changed and _G(actsps) is still
+// create the actsps[aa] image with the object drawn correctly
+// returns 1 if nothing at all has changed and actsps is still
 // intact from last time; 0 otherwise
 int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware) {
 	int useindx = aa;
@@ -1348,7 +1348,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
 		actspsUsed = scale_and_flip_sprite(useindx, coldept, zoom_level,
 		                                   _G(objs)[aa].num, sprwidth, sprheight, isMirrored);
 	} else {
-		// ensure _G(actsps) exists
+		// ensure actsps exists
 		_G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
 	}
 
@@ -1603,7 +1603,7 @@ void prepare_characters_for_drawing() {
 		           (_G(gfxDriver)->HasAcceleratedTransform())) {
 			usingCachedImage = true;
 		} else if (_G(charcache)[aa].inUse) {
-			//destroy_bitmap (_G(charcache)[aa].image);
+			//destroy_bitmap (charcache[aa].image);
 			_G(charcache)[aa].inUse = 0;
 		}
 
@@ -1644,7 +1644,7 @@ void prepare_characters_for_drawing() {
 		// If cache needs to be re-drawn
 		if (!_G(charcache)[aa].inUse) {
 
-			// create the base sprite in _G(actsps)[useindx], which will
+			// create the base sprite in actsps[useindx], which will
 			// be scaled and/or flipped, as appropriate
 			int actspsUsed = 0;
 			if (!_G(gfxDriver)->HasAcceleratedTransform()) {
@@ -1652,7 +1652,7 @@ void prepare_characters_for_drawing() {
 				                 useindx, coldept, zoom_level, sppic,
 				                 newwidth, newheight, isMirrored);
 			} else {
-				// ensure _G(actsps) exists
+				// ensure actsps exists
 				_G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, _GP(game).SpriteInfos[sppic].Width, _GP(game).SpriteInfos[sppic].Height);
 			}
 
@@ -2239,7 +2239,7 @@ void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY
 	render_to_screen();
 
 	if (!SHOULD_QUIT && !_GP(play).screen_is_faded_out) {
-		// always update the _G(palette), regardless of whether the plugin
+		// always update the palette, regardless of whether the plugin
 		// vetos the screen update
 		if (_G(bg_just_changed)) {
 			setpal();
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 237272412d..23639e3a0f 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -133,8 +133,8 @@ void draw_game_screen_callback();
 void GfxDriverOnInitCallback(void *data);
 bool GfxDriverNullSpriteCallback(int x, int y);
 void putpixel_compensate(Shared::Bitmap *g, int xx, int yy, int col);
-// create the _G(actsps)[aa] image with the object drawn correctly
-// returns 1 if nothing at all has changed and _G(actsps) is still
+// create the actsps[aa] image with the object drawn correctly
+// returns 1 if nothing at all has changed and actsps is still
 // intact from last time; 0 otherwise
 int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware);
 void clear_letterbox_borders();
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index f3f3ed5858..ebdd8df2e8 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -52,7 +52,7 @@ int run_claimable_event(const char *tsname, bool includeRoom, int numParams, con
 	*eventWasClaimed = true;
 	// Run the room script function, and if it is not claimed,
 	// then run the main one
-	// We need to remember the _G(eventClaimed) variable's state, in case
+	// We need to remember the eventClaimed variable's state, in case
 	// this is a nested event
 	int eventClaimedOldValue = _G(eventClaimed);
 	_G(eventClaimed) = EVENT_INPROGRESS;
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index edf23b93d5..421cffb950 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -1439,7 +1439,7 @@ void game_sprite_deleted(int sprnum) {
 			_GP(guibuts)[i].NotifyParentChanged();
 		}
 	}
-	// _G(views)
+	// views
 	for (size_t v = 0; v < (size_t)_GP(game).numviews; ++v) {
 		for (size_t l = 0; l < (size_t)_G(views)[v].numLoops; ++l) {
 			for (size_t f = 0; f < (size_t)_G(views)[v].loops[l].numFrames; ++f) {
diff --git a/engines/ags/engine/ac/global_api.cpp b/engines/ags/engine/ac/global_api.cpp
index 1d74109bca..ce9c626945 100644
--- a/engines/ags/engine/ac/global_api.cpp
+++ b/engines/ags/engine/ac/global_api.cpp
@@ -546,7 +546,7 @@ RuntimeScriptValue Sc_GetInvGraphic(const RuntimeScriptValue *params, int32_t pa
 	API_SCALL_INT_PINT(GetInvGraphic);
 }
 
-// void (int indx,char*_G(buff))
+// void (int indx,char*buff)
 RuntimeScriptValue Sc_GetInvName(const RuntimeScriptValue *params, int32_t param_count) {
 	API_SCALL_VOID_PINT_POBJ(GetInvName, char);
 }
diff --git a/engines/ags/engine/ac/global_display.cpp b/engines/ags/engine/ac/global_display.cpp
index 27eadd397a..a8eed12c8c 100644
--- a/engines/ags/engine/ac/global_display.cpp
+++ b/engines/ags/engine/ac/global_display.cpp
@@ -59,7 +59,7 @@ void DisplaySimple(const char *text) {
 }
 
 void DisplayTopBar(int ypos, int ttexcol, int backcol, const char *title, const char *text) {
-	// FIXME: refactor _G(source_text_length) and get rid of this ugly hack!
+	// FIXME: refactor source_text_length and get rid of this ugly hack!
 	const int real_text_sourcelen = _G(source_text_length);
 	snprintf(_GP(topBar).text, sizeof(_GP(topBar).text), "%s", get_translation(title));
 	_G(source_text_length) = real_text_sourcelen;
diff --git a/engines/ags/engine/ac/inventory_item.cpp b/engines/ags/engine/ac/inventory_item.cpp
index 9535c401a9..1325b50b47 100644
--- a/engines/ags/engine/ac/inventory_item.cpp
+++ b/engines/ags/engine/ac/inventory_item.cpp
@@ -134,7 +134,7 @@ RuntimeScriptValue Sc_InventoryItem_CheckInteractionAvailable(void *self, const
 	API_OBJCALL_INT_PINT(ScriptInvItem, InventoryItem_CheckInteractionAvailable);
 }
 
-// void (ScriptInvItem *iitem, char *_G(buff))
+// void (ScriptInvItem *iitem, char *buff)
 RuntimeScriptValue Sc_InventoryItem_GetName(void *self, const RuntimeScriptValue *params, int32_t param_count) {
 	API_OBJCALL_VOID_POBJ(ScriptInvItem, InventoryItem_GetName, char);
 }
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index e4b57e9efb..67ab6a5a1a 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -480,7 +480,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
 	// Make sure the room gfx and masks are matching game's native res
 	convert_room_background_to_game_res();
 
-	// _G(walkable_areas_temp) is used by the pathfinder to generate a
+	// walkable_areas_temp is used by the pathfinder to generate a
 	// copy of the walkable areas - allocate it here to save time later
 	delete _G(walkable_areas_temp);
 	_G(walkable_areas_temp) = BitmapHelper::CreateBitmap(_GP(thisroom).WalkAreaMask->GetWidth(), _GP(thisroom).WalkAreaMask->GetHeight(), 8);
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index c38bf9a77f..90ef251da0 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -338,12 +338,12 @@ int PrepareTextScript(ccInstance *sci, const char **tsname) {
 
 int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, int numParam, const RuntimeScriptValue *params) {
 	int oldRestoreCount = _G(gameHasBeenRestored);
-	// First, save the current _G(ccError) state
+	// First, save the current ccError state
 	// This is necessary because we might be attempting
 	// to run Script B, while Script A is still running in the
 	// background.
 	// If CallInstance here has an error, it would otherwise
-	// also abort Script A because _G(ccError) is a global variable.
+	// also abort Script A because ccError is a global variable.
 	int cachedCcError = _G(ccError);
 	_G(ccError) = 0;
 
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index f36aaac42d..11013f7a96 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -323,7 +323,7 @@ Bitmap glVirtualScreenWrap;
 void IAGSEngine::SetVirtualScreen(BITMAP *bmp) {
 	if (!_G(gfxDriver)->UsesMemoryBackBuffer()) {
 		debug_script_warn("SetVirtualScreen: this plugin requires software graphics driver to work correctly.");
-		// we let it continue since _G(gfxDriver) is supposed to ignore this request without throwing an exception
+		// we let it continue since gfxDriver is supposed to ignore this request without throwing an exception
 	}
 
 	if (bmp) {
diff --git a/engines/ags/plugins/plugin_object_reader.cpp b/engines/ags/plugins/plugin_object_reader.cpp
index 9d630af200..97311623d6 100644
--- a/engines/ags/plugins/plugin_object_reader.cpp
+++ b/engines/ags/plugins/plugin_object_reader.cpp
@@ -25,7 +25,4 @@
 
 namespace AGS3 {
 
-//PluginObjectReader _G(pluginReaders)[MAX_PLUGIN_OBJECT_READERS];
-//int _G(numPluginReaders) = 0;
-
 } // namespace AGS3
diff --git a/engines/ags/plugins/plugin_object_reader.h b/engines/ags/plugins/plugin_object_reader.h
index 294f2dd9d7..342bb2a07d 100644
--- a/engines/ags/plugins/plugin_object_reader.h
+++ b/engines/ags/plugins/plugin_object_reader.h
@@ -28,8 +28,8 @@ namespace AGS3 {
 class IAGSManagedObjectReader;
 
 struct PluginObjectReader {
-IAGSManagedObjectReader *reader;
-const char *type;
+	IAGSManagedObjectReader *reader;
+	const char *type;
 };
 
 } // namespace AGS3


Commit: c7ce28934afe4045a811df3ede88b6f0ecd0e03b
    https://github.com/scummvm/scummvm/commit/c7ce28934afe4045a811df3ede88b6f0ecd0e03b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:00-07:00

Commit Message:
AGS: fixed formatting in SpriteCache::InitFile()

>From upstream 25bc13eb548a5f6e0e8201163809ba038f5b362e

Changed paths:
    engines/ags/shared/ac/sprite_cache.cpp


diff --git a/engines/ags/shared/ac/sprite_cache.cpp b/engines/ags/shared/ac/sprite_cache.cpp
index 677883c3e9..694dad7fc1 100644
--- a/engines/ags/shared/ac/sprite_cache.cpp
+++ b/engines/ags/shared/ac/sprite_cache.cpp
@@ -690,7 +690,7 @@ HError SpriteCache::InitFile(const String &filename, const String &sprindex_file
 
 	_stream.reset(_GP(AssetMgr)->OpenAsset(filename));
 	if (_stream == nullptr)
-		return new Error(String::FromFormat("Failed to open _GP(spriteset) file '%s'.", filename));
+		return new Error(String::FromFormat("Failed to open spriteset file '%s'.", filename.GetCStr()));
 
 	spr_initial_offs = _stream->GetPosition();
 


Commit: 46ddd20145a7c00a27826e8c76ee1fba1a506ef3
    https://github.com/scummvm/scummvm/commit/46ddd20145a7c00a27826e8c76ee1fba1a506ef3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:01-07:00

Commit Message:
AGS: Fixed few type cast warnings

>From upstream 3085660c96318f2fb4943aff6fc41dfcd6a00c3d

Changed paths:
    engines/ags/engine/ac/sys_events.cpp
    engines/ags/engine/debugging/file_based_ags_debugger.cpp
    engines/ags/engine/gui/gui_dialog.cpp
    engines/ags/engine/media/audio/sound.cpp
    engines/ags/engine/media/audio/sound.h
    engines/ags/plugins/ags_plugin.cpp


diff --git a/engines/ags/engine/ac/sys_events.cpp b/engines/ags/engine/ac/sys_events.cpp
index 6ccf1c927f..342067aff9 100644
--- a/engines/ags/engine/ac/sys_events.cpp
+++ b/engines/ags/engine/ac/sys_events.cpp
@@ -180,7 +180,7 @@ int mgetbutton() {
 }
 
 bool ags_misbuttondown(int but) {
-	return mouse_button_poll() & MB_ARRAY[but];
+	return (mouse_button_poll() & MB_ARRAY[but]) != 0;
 }
 
 int ags_mgetbutton() {
diff --git a/engines/ags/engine/debugging/file_based_ags_debugger.cpp b/engines/ags/engine/debugging/file_based_ags_debugger.cpp
index 909617cdf9..479b32aaf9 100644
--- a/engines/ags/engine/debugging/file_based_ags_debugger.cpp
+++ b/engines/ags/engine/debugging/file_based_ags_debugger.cpp
@@ -68,7 +68,7 @@ char *FileBasedAGSDebugger::GetNextMessage() {
 		// check again, because the editor might have deleted the file in the meantime
 		return nullptr;
 	}
-	int fileSize = in->GetLength();
+	soff_t fileSize = in->GetLength();
 	char *msg = (char *)malloc(fileSize + 1);
 	in->Read(msg, fileSize);
 	delete in;
diff --git a/engines/ags/engine/gui/gui_dialog.cpp b/engines/ags/engine/gui/gui_dialog.cpp
index 0c8c0a5e23..d6c361e6ff 100644
--- a/engines/ags/engine/gui/gui_dialog.cpp
+++ b/engines/ags/engine/gui/gui_dialog.cpp
@@ -21,7 +21,6 @@
  */
 
 #include "ags/lib/std/algorithm.h"
-//include <cstdio>
 #include "ags/lib/allegro.h" // find files
 #include "ags/engine/gui/gui_dialog.h"
 #include "ags/shared/ac/common.h"
diff --git a/engines/ags/engine/media/audio/sound.cpp b/engines/ags/engine/media/audio/sound.cpp
index b74be6e350..0b67ca1b23 100644
--- a/engines/ags/engine/media/audio/sound.cpp
+++ b/engines/ags/engine/media/audio/sound.cpp
@@ -40,7 +40,7 @@
 
 namespace AGS3 {
 
-SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, int loop) {
+SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, bool loop) {
 	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		Audio::AudioStream *audioStream = Audio::makeWAVStream(data, DisposeAfterUse::YES);
@@ -86,16 +86,16 @@ SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, int voll) {
 	return my_load_static_ogg(asset_name, voll, false);
 }
 
-SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool repeat) {
+SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool loop) {
 	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
-		return new MYMIDI(data, repeat);
+		return new MYMIDI(data, loop);
 	} else {
 		return nullptr;
 	}
 }
 
-SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool repeat) {
+SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool loop) {
 	Common::SeekableReadStream *data = _GP(AssetMgr)->OpenAssetStream(asset_name.Name, asset_name.Filter);
 	if (data) {
 		// determine the file extension
@@ -126,7 +126,7 @@ SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool repeat) {
 			return nullptr;
 		}
 
-		return new SoundClipWave<MUS_MOD>(audioStream, 255, repeat);
+		return new SoundClipWave<MUS_MOD>(audioStream, 255, loop);
 	} else {
 		return nullptr;
 	}
diff --git a/engines/ags/engine/media/audio/sound.h b/engines/ags/engine/media/audio/sound.h
index ee0e97dffa..c5038f17dd 100644
--- a/engines/ags/engine/media/audio/sound.h
+++ b/engines/ags/engine/media/audio/sound.h
@@ -34,13 +34,13 @@
 
 namespace AGS3 {
 
-SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, int loop);
+SOUNDCLIP *my_load_wave(const AssetPath &asset_name, int voll, bool loop);
 SOUNDCLIP *my_load_mp3(const AssetPath &asset_name, int voll);
 SOUNDCLIP *my_load_static_mp3(const AssetPath &asset_name, int voll, bool loop);
 SOUNDCLIP *my_load_static_ogg(const AssetPath &asset_name, int voll, bool loop);
 SOUNDCLIP *my_load_ogg(const AssetPath &asset_name, int voll);
-SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool repeat);
-SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool repeat);
+SOUNDCLIP *my_load_midi(const AssetPath &asset_name, bool loop);
+SOUNDCLIP *my_load_mod(const AssetPath &asset_name, bool loop);
 
 } // namespace AGS3
 
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 11013f7a96..ede1b0e767 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -536,7 +536,7 @@ void IAGSEngine::PlaySoundChannel(int32 channel, int32 soundType, int32 volume,
 	AssetPath asset_name(filename, "audio");
 
 	if (soundType == PSND_WAVE)
-		newcha = my_load_wave(asset_name, volume, loop);
+		newcha = my_load_wave(asset_name, volume, (loop != 0));
 	else if (soundType == PSND_MP3STREAM)
 		newcha = my_load_mp3(asset_name, volume);
 	else if (soundType == PSND_OGGSTREAM)
@@ -548,10 +548,10 @@ void IAGSEngine::PlaySoundChannel(int32 channel, int32 soundType, int32 volume,
 	else if (soundType == PSND_MIDI) {
 		if (_GP(play).silent_midi != 0 || _G(current_music_type) == MUS_MIDI)
 			quit("!IAGSEngine::PlaySoundChannel: MIDI already in use");
-		newcha = my_load_midi(asset_name, loop);
+		newcha = my_load_midi(asset_name, (loop != 0));
 		newcha->set_volume(volume);
 	} else if (soundType == PSND_MOD) {
-		newcha = my_load_mod(asset_name, loop);
+		newcha = my_load_mod(asset_name, (loop != 0));
 		newcha->set_volume(volume);
 	} else
 		quit("!IAGSEngine::PlaySoundChannel: unknown sound type");


Commit: f982d82cc785a9f937bfb10ae1273635aebc8545
    https://github.com/scummvm/scummvm/commit/f982d82cc785a9f937bfb10ae1273635aebc8545
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:01-07:00

Commit Message:
AGS: Added MemoryStream

Found upstream e3208df5afeed6cef118dc71a0af45cfce72f4d7

Changed paths:
  A engines/ags/shared/util/memory_stream.cpp
  A engines/ags/shared/util/memory_stream.h
    engines/ags/module.mk
    engines/ags/shared/util/stream.h


diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index 2f821ff8d8..f58017b88b 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -81,6 +81,7 @@ MODULE_OBJS = \
 	shared/util/ini_util.o \
 	shared/util/lzw.o \
 	shared/util/misc.o \
+	shared/util/memory_stream.o \
 	shared/util/multi_file_lib.o \
 	shared/util/path.o \
 	shared/util/proxy_stream.o \
diff --git a/engines/ags/shared/util/memory_stream.cpp b/engines/ags/shared/util/memory_stream.cpp
new file mode 100644
index 0000000000..5931e1e243
--- /dev/null
+++ b/engines/ags/shared/util/memory_stream.cpp
@@ -0,0 +1,155 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/lib/std/algorithm.h"
+#include "ags/shared/util/memory_stream.h"
+
+namespace AGS3 {
+namespace AGS {
+namespace Shared {
+
+MemoryStream::MemoryStream(const std::vector<char> &cbuf, DataEndianess stream_endianess)
+	: DataStream(stream_endianess)
+	, _cbuf(&cbuf.front())
+	, _len(cbuf.size())
+	, _buf(nullptr)
+	, _mode(kStream_Read)
+	, _pos(0) {
+}
+
+MemoryStream::MemoryStream(const String &cbuf, DataEndianess stream_endianess)
+	: DataStream(stream_endianess)
+	, _cbuf(cbuf.GetCStr())
+	, _len(cbuf.GetLength())
+	, _buf(nullptr)
+	, _mode(kStream_Read)
+	, _pos(0) {
+}
+
+MemoryStream::MemoryStream(std::vector<char> &buf, StreamWorkMode mode, DataEndianess stream_endianess)
+	: DataStream(stream_endianess)
+	, _len(buf.size())
+	, _buf(&buf)
+	, _mode(mode)
+	, _pos(buf.size()) {
+	_cbuf = (mode == kStream_Read) ? &buf.front() : nullptr;
+}
+
+MemoryStream::~MemoryStream() {
+}
+
+void MemoryStream::Close() {
+	_cbuf = nullptr;
+	_buf = nullptr;
+	_pos = -1;
+}
+
+bool MemoryStream::Flush() {
+	return true;
+}
+
+bool MemoryStream::IsValid() const {
+	return _cbuf != nullptr || _buf != nullptr;
+}
+
+bool MemoryStream::EOS() const {
+	return _pos >= _len;
+}
+
+soff_t MemoryStream::GetLength() const {
+	return _len;
+}
+
+soff_t MemoryStream::GetPosition() const {
+	return _pos;
+}
+
+bool MemoryStream::CanRead() const {
+	return (_cbuf != nullptr) && (_mode == kStream_Read);
+}
+
+bool MemoryStream::CanWrite() const {
+	return (_buf != nullptr) && (_mode == kStream_Write);
+}
+
+bool MemoryStream::CanSeek() const {
+	return CanRead(); // TODO: support seeking in writable stream?
+}
+
+size_t MemoryStream::Read(void *buffer, size_t size) {
+	if (EOS()) {
+		return 0;
+	}
+	soff_t remain = _len - _pos;
+	assert(remain > 0);
+	size_t read_sz = std::min((size_t)remain, size);
+	memcpy(buffer, _cbuf + _pos, read_sz);
+	_pos += read_sz;
+	return read_sz;
+}
+
+int32_t MemoryStream::ReadByte() {
+	if (EOS()) {
+		return -1;
+	}
+	return _cbuf[(size_t)(_pos++)];
+}
+
+size_t MemoryStream::Write(const void *buffer, size_t size) {
+	if (!_buf) {
+		return 0;
+	}
+	_buf->resize(_buf->size() + size);
+	memcpy(_buf->data() + _pos, buffer, size);
+	_pos += size;
+	_len += size;
+	return size;
+}
+
+int32_t MemoryStream::WriteByte(uint8_t val) {
+	if (!_buf) {
+		return -1;
+	}
+	_buf->push_back(val);
+	_pos++; _len++;
+	return val;
+}
+
+bool MemoryStream::Seek(soff_t offset, StreamSeek origin) {
+	if (!CanSeek()) {
+		return false;
+	}
+	switch (origin) {
+	case kSeekBegin:    _pos = 0 + offset; break;
+	case kSeekCurrent:  _pos = _pos + offset; break;
+	case kSeekEnd:      _pos = _len + offset; break;
+	default:
+		return false;
+	}
+	_pos = std::max<soff_t>(0, _pos);
+	_pos = std::min<soff_t>(_len, _pos); // clamp to EOS
+	return true;
+}
+
+} // namespace Shared
+} // namespace AGS
+} // namespace AGS3
diff --git a/engines/ags/shared/util/memory_stream.h b/engines/ags/shared/util/memory_stream.h
new file mode 100644
index 0000000000..5cc717c243
--- /dev/null
+++ b/engines/ags/shared/util/memory_stream.h
@@ -0,0 +1,93 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+//=============================================================================
+//
+// MemoryStream does reading and writing over the buffer of chars stored in
+// memory. Currently has rather trivial implementation. Does not own a buffer
+// itself, but works with the provided std::vector reference, which means that
+// the buffer *must* persist until stream is closed.
+// TODO: perhaps accept const char* for reading mode, for compatibility with
+// the older code, and maybe to let also read String objects?
+// TODO: separate StringStream for reading & writing String object?
+//
+//=============================================================================
+
+#ifndef AGS_SHARED_UTIL_MEMORY_STREAM_H
+#define AGS_SHARED_UTIL_MEMORY_STREAM_H
+
+#include "ags/lib/std/vector.h"
+#include "ags/shared/util/data_stream.h"
+#include "ags/shared/util/string.h"
+
+namespace AGS3 {
+namespace AGS {
+namespace Shared {
+
+class MemoryStream : public DataStream {
+public:
+	// Construct memory stream in the read-only mode over a const std::vector;
+	// vector must persist in memory until the stream is closed.
+	MemoryStream(const std::vector<char> &cbuf, DataEndianess stream_endianess = kLittleEndian);
+	// Construct memory stream in the read-only mode over a const String;
+	// String object must persist in memory until the stream is closed.
+	MemoryStream(const String &cbuf, DataEndianess stream_endianess = kLittleEndian);
+	// Construct memory stream in the chosen mode over a given std::vector;
+	// vector must persist in memory until the stream is closed.
+	MemoryStream(std::vector<char> &buf, StreamWorkMode mode, DataEndianess stream_endianess = kLittleEndian);
+	~MemoryStream() override;
+
+	void    Close() override;
+	bool    Flush() override;
+
+	// Is stream valid (underlying data initialized properly)
+	bool    IsValid() const override;
+	// Is end of stream
+	bool    EOS() const override;
+	// Total length of stream (if known)
+	soff_t  GetLength() const override;
+	// Current position (if known)
+	soff_t  GetPosition() const override;
+	bool    CanRead() const override;
+	bool    CanWrite() const override;
+	bool    CanSeek() const override;
+
+	size_t  Read(void *buffer, size_t size) override;
+	int32_t ReadByte() override;
+	size_t  Write(const void *buffer, size_t size) override;
+	int32_t WriteByte(uint8_t b) override;
+
+	bool    Seek(soff_t offset, StreamSeek origin) override;
+
+private:
+	const char *_cbuf;
+	size_t _len;
+	std::vector<char> *_buf;
+	const StreamWorkMode _mode;
+	soff_t _pos;
+};
+
+} // namespace Shared
+} // namespace AGS
+} // namespace AGS3
+
+#endif
diff --git a/engines/ags/shared/util/stream.h b/engines/ags/shared/util/stream.h
index fd1f322017..4f1f584448 100644
--- a/engines/ags/shared/util/stream.h
+++ b/engines/ags/shared/util/stream.h
@@ -43,6 +43,12 @@ namespace AGS3 {
 namespace AGS {
 namespace Shared {
 
+// TODO: merge with FileWorkMode (historical mistake)
+enum StreamWorkMode {
+	kStream_Read,
+	kStream_Write
+};
+
 class Stream : public IAGSStream {
 public:
 	virtual ~Stream() {}


Commit: edb1ac0f6c769739ac124894cdcfcf0e7c185473
    https://github.com/scummvm/scummvm/commit/edb1ac0f6c769739ac124894cdcfcf0e7c185473
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:01-07:00

Commit Message:
AGS: fixed formatting type for several size_t and soff_t values

>From upstream 548573740a5c8acc48600f9b069b7d1dc94d0dc3

Changed paths:
    engines/ags/engine/debugging/message_buffer.cpp
    engines/ags/engine/game/game_init.cpp
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/game/savegame_components.cpp
    engines/ags/engine/main/engine.cpp
    engines/ags/engine/script/cc_instance.cpp
    engines/ags/shared/ac/sprite_cache.cpp
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/game/room_file.cpp
    engines/ags/shared/game/room_struct.cpp


diff --git a/engines/ags/engine/debugging/message_buffer.cpp b/engines/ags/engine/debugging/message_buffer.cpp
index 23f103139c..039bfb922f 100644
--- a/engines/ags/engine/debugging/message_buffer.cpp
+++ b/engines/ags/engine/debugging/message_buffer.cpp
@@ -52,8 +52,9 @@ void MessageBuffer::Send(const String &out_id) {
 		return;
 	if (_msgLost > 0) {
 		DebugGroup gr = _GP(DbgMgr).GetGroup(kDbgGroup_Main);
-		_GP(DbgMgr).SendMessage(out_id, DebugMessage(String::FromFormat("WARNING: output %s lost exceeding buffer: %u debug messages\n", out_id.GetCStr(), (unsigned)_msgLost),
-		                        gr.UID.ID, gr.OutputName, kDbgMsg_All));
+		_GP(DbgMgr).SendMessage(out_id, DebugMessage(
+			String::FromFormat("WARNING: output %s lost exceeding buffer: %zu debug messages\n", out_id.GetCStr(), (unsigned)_msgLost),
+		    gr.UID.ID, gr.OutputName, kDbgMsg_All));
 	}
 	for (std::vector<DebugMessage>::const_iterator it = _buffer.begin(); it != _buffer.end(); ++it) {
 		_GP(DbgMgr).SendMessage(out_id, *it);
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 4fbabcf6ab..3f300fb30a 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -298,7 +298,8 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
 	if (_GP(game).numfonts == 0)
 		return new GameInitError(kGameInitErr_NoFonts);
 	if (_GP(game).audioClipTypes.size() > MAX_AUDIO_TYPES)
-		return new GameInitError(kGameInitErr_TooManyAudioTypes, String::FromFormat("Required: %u, max: %d", _GP(game).audioClipTypes.size(), MAX_AUDIO_TYPES));
+		return new GameInitError(kGameInitErr_TooManyAudioTypes,
+			String::FromFormat("Required: %zu, max: %zu", _GP(game).audioClipTypes.size(), MAX_AUDIO_TYPES));
 
 	//
 	// 3. Allocate and init game objects
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 2163c1b55e..ae1578de5a 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -561,7 +561,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 				continue;
 			if ((size_t)chan_info.ClipID >= _GP(game).audioClips.size()) {
 				return new SavegameError(kSvgErr_GameObjectInitFailed,
-				                         String::FromFormat("Invalid audio clip index: %d (clip count: %u).", chan_info.ClipID, _GP(game).audioClips.size()));
+					String::FromFormat("Invalid audio clip index: %d (clip count: %zu).", chan_info.ClipID, _GP(game).audioClips.size()));
 			}
 			play_audio_clip_on_channel(i, &_GP(game).audioClips[chan_info.ClipID],
 			                           chan_info.Priority, chan_info.Repeat, chan_info.Pos);
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 86a17bdde9..2ceef6e8c5 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -1207,9 +1207,9 @@ HSaveError ReadAll(Stream *in, SavegameVersion svg_version, const PreservedParam
 		HSaveError err = ReadComponent(in, hlp, info);
 		if (!err) {
 			return new SavegameError(kSvgErr_ComponentUnserialization,
-			                         String::FromFormat("(#%d) %s, version %i, at offset %u.",
-			                                 idx, info.Name.IsEmpty() ? "unknown" : info.Name.GetCStr(), info.Version, info.Offset),
-			                         err);
+			    String::FromFormat("(#%d) %s, version %i, at offset %lld.",
+					idx, info.Name.IsEmpty() ? "unknown" : info.Name.GetCStr(), info.Version, info.Offset),
+				err);
 		}
 		update_polled_stuff_if_runtime();
 		idx++;
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index c67dd79078..e5284686bc 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -1064,7 +1064,7 @@ static void engine_print_info(const std::set<String> &keys, ConfigTree *user_cfg
 		StringV drv;
 		AGS::Engine::GetGfxDriverFactoryNames(drv);
 		for (size_t i = 0; i < drv.size(); ++i) {
-			data["graphicdriver"][String::FromFormat("%u", i)] = drv[i];
+			data["graphicdriver"][String::FromFormat("%zu", i)] = drv[i];
 		}
 	}
 	if (all || keys.count("configpath") > 0) {
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 0af7ecb4a3..0280309019 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -1095,7 +1095,7 @@ int ccInstance::Run(int32_t curpc) {
 		case SCMD_NEWUSEROBJECT: {
 			const int32_t size = arg2.IValue;
 			if (size < 0) {
-				cc_error("Invalid size for user object; requested: %u (or %d), range: 0..%d", (uint32_t)size, size, INT_MAX);
+				cc_error("Invalid size for user object; requested: %d (or %d), range: 0..%d", (uint32_t)size, size, INT_MAX);
 				return -1;
 			}
 			ScriptUserObject *suo = ScriptUserObject::CreateManaged(size);
diff --git a/engines/ags/shared/ac/sprite_cache.cpp b/engines/ags/shared/ac/sprite_cache.cpp
index 694dad7fc1..c655323d07 100644
--- a/engines/ags/shared/ac/sprite_cache.cpp
+++ b/engines/ags/shared/ac/sprite_cache.cpp
@@ -468,7 +468,7 @@ size_t SpriteCache::LoadSprite(sprkey_t index) {
 	_cacheSize += size;
 
 #ifdef DEBUG_SPRITECACHE
-	Debug::Printf(kDbgGroup_SprCache, kDbgMsg_Debug, "Loaded %d, size now %u KB", index, _cacheSize / 1024);
+	Debug::Printf(kDbgGroup_SprCache, kDbgMsg_Debug, "Loaded %d, size now %zu KB", index, _cacheSize / 1024);
 #endif
 
 	return size;
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index c8935dde28..f8b5628cb0 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -379,7 +379,7 @@ HGameFileError ReadPlugins(std::vector<PluginInfo> &infos, Stream *in) {
 		size_t datasize = in->ReadInt32();
 		// just check for silly datasizes
 		if (datasize > PLUGIN_SAVEBUFFERSIZE)
-			return new MainGameFileError(kMGFErr_PluginDataSizeTooLarge, String::FromFormat("Required: %u, max: %u", datasize, PLUGIN_SAVEBUFFERSIZE));
+			return new MainGameFileError(kMGFErr_PluginDataSizeTooLarge, String::FromFormat("Required: %zu, max: %zu", datasize, (size_t)PLUGIN_SAVEBUFFERSIZE));
 
 		PluginInfo info;
 		info.Name = name;
@@ -663,7 +663,7 @@ HGameFileError ReadSpriteFlags(LoadedGameEntities &ents, Stream *in, GameDataVer
 	else
 		sprcount = in->ReadInt32();
 	if (sprcount > (size_t)SpriteCache::MAX_SPRITE_INDEX + 1)
-		return new MainGameFileError(kMGFErr_TooManySprites, String::FromFormat("Count: %u, max: %u", sprcount, (uint32_t)SpriteCache::MAX_SPRITE_INDEX + 1));
+		return new MainGameFileError(kMGFErr_TooManySprites, String::FromFormat("Count: %zu, max: %zu", sprcount, (size_t)SpriteCache::MAX_SPRITE_INDEX + 1));
 
 	ents.SpriteCount = sprcount;
 	ents.SpriteFlags.clear();
@@ -787,9 +787,9 @@ HGameFileError ReadGameData(LoadedGameEntities &ents, Stream *in, GameDataVersio
 		soff_t cur_pos = in->GetPosition();
 		if (cur_pos > block_end) {
 			return new MainGameFileError(kMGFErr_ExtBlockDataOverlapping,
-			                             String::FromFormat("Extension: %s, expected to end at offset: %u, finished reading at %u.", ext_id.GetCStr(), block_end, cur_pos));
+				String::FromFormat("Extension: %s, expected to end at offset: %lld, finished reading at %lld.", ext_id.GetCStr(), block_end, cur_pos));
 		} else if (cur_pos < block_end) {
-			Debug::Printf(kDbgMsg_Warn, "WARNING: game data blocks nonsequential, ext %s expected to end at %u, finished reading at %u",
+			Debug::Printf(kDbgMsg_Warn, "WARNING: game data blocks nonsequential, ext %s expected to end at %lld, finished reading at %lld",
 			              ext_id.GetCStr(), block_end, cur_pos);
 			in->Seek(block_end, Shared::kSeekBegin);
 		}
diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index 36cdb4c61c..7276d4144e 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -616,7 +616,7 @@ HRoomFileError ReadRoomData(RoomStruct *room, Stream *in, RoomFileVersion data_v
 			                         String::FromFormat("Block: %s, expected to end at offset: %u, finished reading at %u.",
 			                                 ext_id.GetCStr(), block_end, cur_pos));
 		} else if (cur_pos < block_end) {
-			Debug::Printf(kDbgMsg_Warn, "WARNING: room data blocks nonsequential, block type %s expected to end at %u, finished reading at %u",
+			Debug::Printf(kDbgMsg_Warn, "WARNING: room data blocks nonsequential, block type %s expected to end at %lld, finished reading at %lld",
 			              ext_id.GetCStr(), block_end, cur_pos);
 			in->Seek(block_end, Shared::kSeekBegin);
 		}
diff --git a/engines/ags/shared/game/room_struct.cpp b/engines/ags/shared/game/room_struct.cpp
index 32521756bf..ce3794e93d 100644
--- a/engines/ags/shared/game/room_struct.cpp
+++ b/engines/ags/shared/game/room_struct.cpp
@@ -170,7 +170,7 @@ void RoomStruct::InitDefaults() {
 		if (i == 0)
 			Hotspots[i].Name = "No hotspot";
 		else
-			Hotspots[i].Name.Format("Hotspot %u", i);
+			Hotspots[i].Name.Format("Hotspot %zu", i);
 	}
 	for (size_t i = 0; i < (size_t)MAX_ROOM_OBJECTS; ++i)
 		Objects[i] = RoomObjectInfo();


Commit: 2f54b35c651be52d8c9f92b4ad8f4fb6ef70acad
    https://github.com/scummvm/scummvm/commit/2f54b35c651be52d8c9f92b4ad8f4fb6ef70acad
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:02-07:00

Commit Message:
AGS: fixed CreateStringArray() not adding managed string refs

>From upstream 37ac36bac03584f2f5c2cacd0a226f5d0c669e9f

Changed paths:
    engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp


diff --git a/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp b/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
index dacec6d73f..9a51ede626 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
@@ -142,8 +142,12 @@ DynObjectRef DynamicArrayHelpers::CreateStringArray(const std::vector<const char
 	int32_t *slots = static_cast<int32_t *>(arr.second);
 	for (auto s : items) {
 		DynObjectRef str = _G(stringClassImpl)->CreateString(s);
+		// We must add reference count, because the string is going to be saved
+		// within another object (array), not returned to script directly
+		ccAddObjectReference(str.first);
 		*(slots++) = str.first;
 	}
+
 	return arr;
 }
 


Commit: 8d7e13bea7f1d7403bd4ae19230d03e454811b88
    https://github.com/scummvm/scummvm/commit/8d7e13bea7f1d7403bd4ae19230d03e454811b88
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:02-07:00

Commit Message:
AGS: fixed crash when displaying text window overlay with no text

>From upstream 970f9c1d0ef20d4b1bd4e643b78091ebe374f68b

Changed paths:
    engines/ags/engine/ac/display.cpp


diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index aa753e78be..fa66e0a8af 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include "ags/lib/std/algorithm.h"
 #include "ags/lib/std/math.h"
 #include "ags/engine/ac/display.h"
 #include "ags/shared/ac/common.h"
@@ -163,7 +164,10 @@ int _display_main(int xx, int yy, int wii, const char *text, int disp_type, int
 	if (disp_type < DISPLAYTEXT_NORMALOVERLAY)
 		remove_screen_overlay(OVER_TEXTMSG); // remove any previous blocking texts
 
-	Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap((wii > 0) ? wii : 2, disp.fulltxtheight + extraHeight, _GP(game).GetColorDepth());
+	const int bmp_width = std::max(2, wii);
+	const int bmp_height = std::max(2, disp.fulltxtheight + extraHeight);
+	Bitmap *text_window_ds = BitmapHelper::CreateTransparentBitmap(
+		bmp_width, bmp_height, _GP(game).GetColorDepth());
 
 	// inform draw_text_window to free the old bitmap
 	const bool wantFreeScreenop = true;


Commit: 15b90c14f3c56086d96e9699f89e5eb18570cd56
    https://github.com/scummvm/scummvm/commit/15b90c14f3c56086d96e9699f89e5eb18570cd56
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:03-07:00

Commit Message:
AGS: picked out VideoMemoryGraphicsDriver::CreateDDB()

>From upstream baae1b880a6e0e8ae96007c72eda2408147158fa

Changed paths:
    engines/ags/engine/gfx/gfx_driver_base.cpp
    engines/ags/engine/gfx/gfx_driver_base.h


diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index aa39851f53..c6e28a2456 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -161,6 +161,13 @@ bool VideoMemoryGraphicsDriver::GetStageMatrixes(RenderMatrixes &rm) {
 	return true;
 }
 
+IDriverDependantBitmap *VideoMemoryGraphicsDriver::CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, bool opaque) {
+	IDriverDependantBitmap * ddb = CreateDDB(bitmap->GetWidth(), bitmap->GetHeight(), bitmap->GetColorDepth(), opaque);
+	if (ddb)
+		UpdateDDBFromBitmap(ddb, bitmap, hasAlpha);
+	return ddb;
+}
+
 PBitmap VideoMemoryGraphicsDriver::CreateStageScreen(size_t index, const Size &sz) {
 	if (_stageScreens.size() <= index)
 		_stageScreens.resize(index + 1);
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index 7eb5837f0b..a3b921f9db 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -202,8 +202,12 @@ public:
 	void SetMemoryBackBuffer(Bitmap *backBuffer) override;
 	Bitmap *GetStageBackBuffer(bool mark_dirty) override;
 	bool GetStageMatrixes(RenderMatrixes &rm) override;
+	IDriverDependantBitmap *CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, bool opaque = false) override;
 
 protected:
+	// Creates a "raw" DDB, without pixel initialization
+	virtual IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque = false) = 0;
+
 	// Stage screens are raw bitmap buffers meant to be sent to plugins on demand
 	// at certain drawing stages. If used at least once these buffers are then
 	// rendered as additional sprites in their respected order.


Commit: c04665d442b9e0fda990823868d4f42548ca3f10
    https://github.com/scummvm/scummvm/commit/c04665d442b9e0fda990823868d4f42548ca3f10
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:03-07:00

Commit Message:
AGS: fixed ChangeRoom for <=2.72 games moving character too early

>From upstream 037185cc42bc693dd5f2fc234f6f295122c70e33

Changed paths:
    engines/ags/engine/ac/character.cpp


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 1ce22447ce..040bd67f7a 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -224,19 +224,17 @@ void Character_ChangeRoomSetLoop(CharacterInfo *chaa, int room, int x, int y, in
 	}
 
 	if ((x != SCR_NO_VALUE) && (y != SCR_NO_VALUE)) {
+		// We cannot set character position right away,
+		// because room switch will occur only after the script end,
+		// and character position may be still changing meanwhile.
 		_G(new_room_pos) = 0;
 
-		if (_G(loaded_game_file_version) <= kGameVersion_272) {
-			// Set position immediately on 2.x.
-			chaa->x = x;
-			chaa->y = y;
-		} else {
-			// don't check X or Y bounds, so that they can do a
-			// walk-in animation if they want
-			_G(new_room_x) = x;
-			_G(new_room_y) = y;
-			if (direction != SCR_NO_VALUE) _G(new_room_loop) = direction;
-		}
+		// don't check X or Y bounds, so that they can do a
+		// walk-in animation if they want
+		_G(new_room_x) = x;
+		_G(new_room_y) = y;
+		if (direction != SCR_NO_VALUE)
+			_G(new_room_loop) = direction;
 	}
 
 	NewRoom(room);


Commit: 8dc2d1beae1e343a0d5f04f413849a5c74c6d69c
    https://github.com/scummvm/scummvm/commit/8dc2d1beae1e343a0d5f04f413849a5c74c6d69c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:03-07:00

Commit Message:
AGS: fixed debug mode reset on restoring a save game

>From upstream c69feac4d24e909e43221185293e4b07a768c6be

Changed paths:
    engines/ags/engine/game/savegame.cpp


diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index ae1578de5a..3ca08af04d 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -41,6 +41,7 @@
 #include "ags/shared/ac/sprite_cache.h"
 #include "ags/engine/ac/system.h"
 #include "ags/engine/ac/timer.h"
+#include "ags/engine/debugging/debugger.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/engine/device/mouse_w32.h"
 #include "ags/shared/gfx/bitmap.h"
@@ -445,6 +446,10 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 	else if ((pp.SpeechVOX >= 0) && (_GP(play).want_speech < 0))
 		_GP(play).want_speech = (-_GP(play).want_speech) - 1;
 
+	// Restore debug flags
+	if (_G(debug_flags) & DBG_DEBUGMODE)
+		_GP(play).debug_mode = 1;
+
 	// recache queued clips
 	for (int i = 0; i < _GP(play).new_music_queue_size; ++i) {
 		_GP(play).new_music_queue[i].cachedClip = nullptr;


Commit: 8333270f719db1b665415d8349889a58e624e7ce
    https://github.com/scummvm/scummvm/commit/8333270f719db1b665415d8349889a58e624e7ce
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:04-07:00

Commit Message:
AGS: Assetmanager SetSearchPriority never set priority fix

>From upstream a908c372a3abcda34049eb0d3bbfaf2378b63147

Changed paths:
    engines/ags/shared/core/asset_manager.cpp


diff --git a/engines/ags/shared/core/asset_manager.cpp b/engines/ags/shared/core/asset_manager.cpp
index 77cdd0b014..3df043d1e4 100644
--- a/engines/ags/shared/core/asset_manager.cpp
+++ b/engines/ags/shared/core/asset_manager.cpp
@@ -85,7 +85,7 @@ AssetManager::AssetManager() {
 }
 
 void AssetManager::SetSearchPriority(AssetSearchPriority priority) {
-	_libsByPriority.Priority = kAssetPriorityDir;
+	_libsByPriority.Priority = priority;
 
 	std::sort(_activeLibs.begin(), _activeLibs.end(), _libsByPriority);
 }


Commit: 08cd34ecbce3ac14c6206f2cc3e262886f8f19a7
    https://github.com/scummvm/scummvm/commit/08cd34ecbce3ac14c6206f2cc3e262886f8f19a7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:04-07:00

Commit Message:
AGS: Misleading set outline in fonts.cpp

>From upstream 4a86b7280b8804ff6b5696b60e4005236ff5d769

Changed paths:
    engines/ags/shared/font/fonts.cpp


diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index eb7d06d014..1a32d80736 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -137,7 +137,7 @@ int get_font_outline(size_t font_number) {
 void set_font_outline(size_t font_number, int outline_type) {
 	if (font_number >= _GP(fonts).size())
 		return;
-	_GP(fonts)[font_number].Info.Outline = FONT_OUTLINE_AUTO;
+	_GP(fonts)[font_number].Info.Outline = outline_type;
 }
 
 int getfontheight(size_t fontNumber) {


Commit: c7365214d13eedfad6aa46703ff3c43d4505e067
    https://github.com/scummvm/scummvm/commit/c7365214d13eedfad6aa46703ff3c43d4505e067
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:05-07:00

Commit Message:
AGS: improved the way view clips are remapped for old audio system

>From upstream 525e0bb3de701f1066ca7ff51cbb6a33877390fc

Changed paths:
    engines/ags/engine/ac/global_view_frame.cpp
    engines/ags/engine/ac/view_frame.cpp
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/media/audio/audio.cpp
    engines/ags/shared/ac/view.cpp
    engines/ags/shared/ac/view.h
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/game/main_game_file.h


diff --git a/engines/ags/engine/ac/global_view_frame.cpp b/engines/ags/engine/ac/global_view_frame.cpp
index 562f10315e..04a7cd5e22 100644
--- a/engines/ags/engine/ac/global_view_frame.cpp
+++ b/engines/ags/engine/ac/global_view_frame.cpp
@@ -48,7 +48,9 @@ void SetFrameSound(int vii, int loop, int frame, int sound) {
 		if (clip == nullptr)
 			quitprintf("!SetFrameSound: audio clip aSound%d not found", sound);
 
-		_G(views)[vii].loops[loop].frames[frame].sound = clip->id + (_GP(game).IsLegacyAudioSystem() ? 0x10000000 : 0);
+		_G(views)[vii].loops[loop].frames[frame].sound =
+			_GP(game).IsLegacyAudioSystem() ? sound : clip->id;
+		_G(views)[vii].loops[loop].frames[frame].audioclip = clip->id;
 	}
 }
 
diff --git a/engines/ags/engine/ac/view_frame.cpp b/engines/ags/engine/ac/view_frame.cpp
index 32af3dd4cb..f199e774d1 100644
--- a/engines/ags/engine/ac/view_frame.cpp
+++ b/engines/ags/engine/ac/view_frame.cpp
@@ -83,14 +83,16 @@ int ViewFrame_GetSound(ScriptViewFrame *svf) {
 
 void ViewFrame_SetSound(ScriptViewFrame *svf, int newSound) {
 	if (newSound < 1) {
-		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].sound = -1;
+		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].audioclip = -1;
 	} else {
 		// convert sound number to audio clip
 		ScriptAudioClip *clip = GetAudioClipForOldStyleNumber(_GP(game), false, newSound);
 		if (clip == nullptr)
 			quitprintf("!SetFrameSound: audio clip aSound%d not found", newSound);
 
-		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].sound = clip->id + (_GP(game).IsLegacyAudioSystem() ? 0x10000000 : 0);
+		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].sound =
+			_GP(game).IsLegacyAudioSystem() ? newSound : clip->id;
+		_G(views)[svf->view].loops[svf->loop].frames[svf->frame].audioclip = clip->id;
 	}
 }
 
@@ -127,17 +129,17 @@ void precache_view(int view) {
 void CheckViewFrame(int view, int loop, int frame, int sound_volume) {
 	ScriptAudioChannel *channel = nullptr;
 	if (_GP(game).IsLegacyAudioSystem()) {
-		if (_G(views)[view].loops[loop].frames[frame].sound > 0) {
-			if (_G(views)[view].loops[loop].frames[frame].sound < 0x10000000) {
-				ScriptAudioClip *clip = GetAudioClipForOldStyleNumber(_GP(game), false, _G(views)[view].loops[loop].frames[frame].sound);
-				if (clip)
-					_G(views)[view].loops[loop].frames[frame].sound = clip->id + 0x10000000;
-				else {
-					_G(views)[view].loops[loop].frames[frame].sound = 0;
+		// sound field contains legacy sound num, so we also need an actual clip index
+		const int sound = _G(views)[view].loops[loop].frames[frame].sound;
+		int &clip_id = _G(views)[view].loops[loop].frames[frame].audioclip;
+		if (sound > 0) {
+			if (clip_id < 0) {
+				ScriptAudioClip *clip = GetAudioClipForOldStyleNumber(_GP(game), false, sound);
+				if (!clip)
 					return;
-				}
+				clip_id = clip->id;
 			}
-			channel = play_audio_clip_by_index(_G(views)[view].loops[loop].frames[frame].sound - 0x10000000);
+			channel = play_audio_clip_by_index(clip_id);
 		}
 	} else {
 		if (_G(views)[view].loops[loop].frames[frame].sound >= 0) {
@@ -151,7 +153,6 @@ void CheckViewFrame(int view, int loop, int frame, int sound_volume) {
 		if (ch)
 			ch->set_volume_percent(ch->get_volume() * sound_volume / 100);
 	}
-
 }
 
 // draws a view frame, flipped if appropriate
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 3ca08af04d..aeefb16a02 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -455,6 +455,9 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
 		_GP(play).new_music_queue[i].cachedClip = nullptr;
 	}
 
+	// Remap old sound nums in case we restored a save having a different list of audio clips
+	RemapLegacySoundNums(_GP(game), _G(views), _G(loaded_game_file_version));
+
 	// restore these to the ones retrieved from the save game
 	const size_t dynsurf_num = Math::Min((uint)MAX_DYNAMIC_SURFACES, r_data.DynamicSurfaces.size());
 	for (size_t i = 0; i < dynsurf_num; ++i) {
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index 1fca23a6f7..137c2ce0ef 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -489,27 +489,18 @@ void stop_and_destroy_channel(int chid) {
 // ***** BACKWARDS COMPATIBILITY WITH OLD AUDIO SYSTEM ***** //
 
 int get_old_style_number_for_sound(int sound_number) {
-	int audio_clip_id = 0;
-
+	// In the legacy audio system treat sound_number as an old style number
 	if (_GP(game).IsLegacyAudioSystem()) {
-		// No sound assigned.
-		if (sound_number < 1)
-			return 0;
-
-		// Sound number is not yet updated to audio clip id.
-		if (sound_number <= 0x10000000)
-			return sound_number;
-
-		// Remove audio clip id flag.
-		audio_clip_id = sound_number - 0x10000000;
-	} else
-		audio_clip_id = sound_number;
+		return sound_number;
+	}
 
-	if (audio_clip_id >= 0) {
+	// Treat sound number as a real clip index
+	if (sound_number >= 0) {
 		int old_style_number = 0;
-		if (sscanf(_GP(game).audioClips[audio_clip_id].scriptName.GetCStr(), "aSound%d", &old_style_number) == 1)
+		if (sscanf(_GP(game).audioClips[sound_number].scriptName.GetCStr(), "aSound%d", &old_style_number) == 1)
 			return old_style_number;
 	}
+
 	return 0;
 }
 
diff --git a/engines/ags/shared/ac/view.cpp b/engines/ags/shared/ac/view.cpp
index 8aab2f41ec..14fa8e5751 100644
--- a/engines/ags/shared/ac/view.cpp
+++ b/engines/ags/shared/ac/view.cpp
@@ -20,7 +20,6 @@
  *
  */
 
-//include <string.h>
 #include "ags/shared/ac/view.h"
 #include "ags/shared/util/aligned_stream.h"
 
@@ -35,7 +34,8 @@ ViewFrame::ViewFrame()
 	, yoffs(0)
 	, speed(0)
 	, flags(0)
-	, sound(0) {
+	, sound(0)
+	, audioclip(-1) {
 	reserved_for_future[0] = 0;
 	reserved_for_future[1] = 0;
 }
@@ -47,8 +47,8 @@ void ViewFrame::ReadFromFile(Stream *in) {
 	speed = in->ReadInt16();
 	flags = in->ReadInt32();
 	sound = in->ReadInt32();
-	reserved_for_future[0] = in->ReadInt32();
-	reserved_for_future[1] = in->ReadInt32();
+	in->ReadInt32(); // reserved 1
+	in->ReadInt32(); // reserved 1
 }
 
 void ViewFrame::WriteToFile(Stream *out) {
@@ -58,8 +58,8 @@ void ViewFrame::WriteToFile(Stream *out) {
 	out->WriteInt16(speed);
 	out->WriteInt32(flags);
 	out->WriteInt32(sound);
-	out->WriteInt32(reserved_for_future[0]);
-	out->WriteInt32(reserved_for_future[1]);
+	out->WriteInt32(0);
+	out->WriteInt32(0);
 }
 
 ViewLoopNew::ViewLoopNew()
diff --git a/engines/ags/shared/ac/view.h b/engines/ags/shared/ac/view.h
index e05863aea3..742da5a93e 100644
--- a/engines/ags/shared/ac/view.h
+++ b/engines/ags/shared/ac/view.h
@@ -43,7 +43,10 @@ struct ViewFrame {
 	short speed;
 	int   flags;
 	int   sound;  // play sound when this frame comes round
-	int   reserved_for_future[2];
+	int   reserved_for_future[2]; // kept only for plugin api
+	// not saved, set at runtime only
+	int audioclip; // actual audio clip reference (in case sound is a legacy number)
+
 	ViewFrame();
 
 	void ReadFromFile(Shared::Stream *in);
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index f8b5628cb0..ffff8cfd1b 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -482,7 +482,7 @@ void UpgradeFonts(GameSetupStruct &game, GameDataVersion data_ver) {
 }
 
 // Convert audio data to the current version
-void UpgradeAudio(GameSetupStruct &game, GameDataVersion data_ver) {
+void UpgradeAudio(GameSetupStruct &game, LoadedGameEntities &ents, GameDataVersion data_ver) {
 	if (data_ver >= kGameVersion_320)
 		return;
 
@@ -551,8 +551,7 @@ void UpgradeAudio(GameSetupStruct &game, GameDataVersion data_ver) {
 	_GP(game).audioClipTypes = audiocliptypes;
 	_GP(game).audioClips = audioclips;
 
-	// Setup sound clip played on score event
-	_GP(game).scoreClipID = -1;
+	RemapLegacySoundNums(game, ents.Views, data_ver);
 }
 
 // Convert character data to the current version
@@ -600,15 +599,26 @@ void UpgradeMouseCursors(GameSetupStruct &game, GameDataVersion data_ver) {
 }
 
 // Adjusts score clip id, depending on game data version
-void AdjustScoreSound(GameSetupStruct &game, GameDataVersion data_ver) {
-	if (data_ver < kGameVersion_320) {
-		_GP(game).scoreClipID = -1;
-		if (_GP(game).options[OPT_SCORESOUND] > 0) {
-			ScriptAudioClip *clip = GetAudioClipForOldStyleNumber(game, false, _GP(game).options[OPT_SCORESOUND]);
-			if (clip)
-				_GP(game).scoreClipID = clip->id;
-			else
-				_GP(game).scoreClipID = -1;
+void RemapLegacySoundNums(GameSetupStruct &game, ViewStruct *&views, GameDataVersion data_ver) {
+	if (data_ver >= kGameVersion_320)
+		return;
+
+	// Setup sound clip played on score event
+	game.scoreClipID = -1;
+	if (game.options[OPT_SCORESOUND] > 0) {
+		ScriptAudioClip *clip = GetAudioClipForOldStyleNumber(game, false, game.options[OPT_SCORESOUND]);
+		if (clip)
+			game.scoreClipID = clip->id;
+	}
+
+	// Reset view frame clip refs
+	// NOTE: we do not map these to real clips right away,
+	// instead we do this at runtime whenever we find a non-mapped frame sound.
+	for (size_t v = 0; v < (size_t)game.numviews; ++v) {
+		for (size_t l = 0; l < (size_t)views[v].numLoops; ++l) {
+			for (size_t f = 0; f < (size_t)views[v].loops[l].numFrames; ++f) {
+				views[v].loops[l].frames[f].audioclip = -1;
+			}
 		}
 	}
 }
@@ -802,26 +812,25 @@ HGameFileError UpdateGameData(LoadedGameEntities &ents, GameDataVersion data_ver
 	GameSetupStruct &game = ents.Game;
 	ApplySpriteData(game, ents, data_ver);
 	UpgradeFonts(game, data_ver);
-	UpgradeAudio(game, data_ver);
-	AdjustScoreSound(game, data_ver);
+	UpgradeAudio(game, ents, data_ver);
 	UpgradeCharacters(game, data_ver);
 	UpgradeMouseCursors(game, data_ver);
 	SetDefaultGlobalMessages(game);
 	// Global talking animation speed
 	if (data_ver < kGameVersion_312) {
 		// Fix animation speed for old formats
-		_GP(game).options[OPT_GLOBALTALKANIMSPD] = 5;
+		game.options[OPT_GLOBALTALKANIMSPD] = 5;
 	} else if (data_ver < kGameVersion_330) {
 		// Convert game option for 3.1.2 - 3.2 games
-		_GP(game).options[OPT_GLOBALTALKANIMSPD] = _GP(game).options[OPT_GLOBALTALKANIMSPD] != 0 ? 5 : (-5 - 1);
+		game.options[OPT_GLOBALTALKANIMSPD] = game.options[OPT_GLOBALTALKANIMSPD] != 0 ? 5 : (-5 - 1);
 	}
 	// Old dialog options API for pre-3.4.0.2 games
 	if (data_ver < kGameVersion_340_2) {
-		_GP(game).options[OPT_DIALOGOPTIONSAPI] = -1;
+		game.options[OPT_DIALOGOPTIONSAPI] = -1;
 	}
 	// Relative asset resolution in pre-3.5.0.8 (always enabled)
 	if (data_ver < kGameVersion_350) {
-		_GP(game).options[OPT_RELATIVEASSETRES] = 1;
+		game.options[OPT_RELATIVEASSETRES] = 1;
 	}
 	FixupSaveDirectory(game);
 	return HGameFileError::None();
diff --git a/engines/ags/shared/game/main_game_file.h b/engines/ags/shared/game/main_game_file.h
index 69643b7023..e4a1903270 100644
--- a/engines/ags/shared/game/main_game_file.h
+++ b/engines/ags/shared/game/main_game_file.h
@@ -161,6 +161,8 @@ void               PreReadGameData(GameSetupStruct &game, Stream *in, GameDataVe
 HGameFileError     UpdateGameData(LoadedGameEntities &ents, GameDataVersion data_ver);
 // Ensures that the game saves directory path is valid
 void               FixupSaveDirectory(GameSetupStruct &game);
+// Maps legacy sound numbers to real audio clips
+void               RemapLegacySoundNums(GameSetupStruct &game, ViewStruct *&views, GameDataVersion data_ver);
 
 } // namespace Shared
 } // namespace AGS


Commit: 9e4bb9140328aeadd657a2d91b7f0b5f488ec476
    https://github.com/scummvm/scummvm/commit/9e4bb9140328aeadd657a2d91b7f0b5f488ec476
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:05-07:00

Commit Message:
AGS: Reintroduced a suspend mode in waitForNextFrame

>From upstream 81aa5509e929442ef8ba6eadf3dccaf3e0e7b818

Changed paths:
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/timer.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 421cffb950..8dbb57be83 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -1231,9 +1231,9 @@ void display_switch_out() {
 
 // Called when game looses input focus and must pause until focus is returned
 void display_switch_out_suspend() {
-	display_switch_out();
-
 	_G(switching_away_from_game)++;
+	_G(game_update_suspend)++;
+	display_switch_out();
 
 	_G(platform)->PauseApplication();
 
@@ -1263,6 +1263,7 @@ void display_switch_in() {
 	// If auto lock option is set, lock mouse to the game window
 	if (_GP(usetup).mouse_auto_lock && _GP(scsystem).windowed)
 		_GP(mouse).TryLockToWindow();
+	_G(switched_away) = false;
 }
 
 // Called when game gets input focus and must resume after pause
@@ -1286,6 +1287,7 @@ void display_switch_in_resume() {
 	// TODO: find out if anything has to be done here for SDL backend
 
 	_G(platform)->ResumeApplication();
+	_G(game_update_suspend)--;
 }
 
 void replace_tokens(const char *srcmes, char *destm, int maxlen) {
diff --git a/engines/ags/engine/ac/timer.cpp b/engines/ags/engine/ac/timer.cpp
index 6d263f04c6..a7c8d889c6 100644
--- a/engines/ags/engine/ac/timer.cpp
+++ b/engines/ags/engine/ac/timer.cpp
@@ -23,6 +23,7 @@
 #include "ags/lib/std/thread.h"
 #include "ags/engine/ac/timer.h"
 #include "ags/shared/core/platform.h"
+#include "ags/engine/ac/sys_events.h"
 #include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/ags.h"
 #include "ags/globals.h"
@@ -59,6 +60,11 @@ void WaitForNextFrame() {
 	// early exit if we're trying to maximise framerate
 	if (frameDuration <= std::chrono::milliseconds::zero()) {
 		_G(next_frame_timestamp) = now;
+		// suspend while the game is being switched out
+		while (_G(game_update_suspend) > 0) {
+			sys_evt_process_pending();
+			_G(platform)->YieldCPU();
+		}
 		return;
 	}
 
@@ -73,6 +79,12 @@ void WaitForNextFrame() {
 	}
 
 	_G(next_frame_timestamp) += frameDuration;
+
+	// suspend while the game is being switched out
+	while (_G(game_update_suspend) > 0) {
+		sys_evt_process_pending();
+		_G(platform)->YieldCPU();
+	}
 }
 
 void skipMissedTicks() {
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 81a1189056..3a9087e256 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -754,6 +754,7 @@ public:
 	char _gamefilenamebuf[200] = { 0 };
 	int _gameHasBeenRestored = 0;
 	int _oldeip = 0;
+	int _game_update_suspend = 0;
 
 	/**@}*/
 


Commit: 45313d50df073e1c4b4b99bda76dcf6a02b780ab
    https://github.com/scummvm/scummvm/commit/45313d50df073e1c4b4b99bda76dcf6a02b780ab
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:06-07:00

Commit Message:
AGS: Moved platform variable macros to core/platform.h

>From upstream ce07581b0b6d3e3ec9f82356dd6422d8691cd473

Changed paths:
    engines/ags/engine/main/engine.cpp
    engines/ags/shared/core/platform.h


diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index e5284686bc..52ceb8fb50 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -882,13 +882,6 @@ void allegro_bitmap_test_init() {
 	//test_allegro_bitmap = AllegroBitmap::CreateBitmap(320,200,32);
 }
 
-// Only allow searching around for game data on desktop systems;
-// otherwise use explicit argument either from program wrapper, command-line
-// or read from default config.
-#if AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX || AGS_PLATFORM_OS_MACOS
-#define AGS_SEARCH_FOR_GAME_ON_LAUNCH
-#endif
-
 // Define location of the game data either using direct settings or searching
 // for the available resource packs in common locations.
 // Returns two paths:
@@ -913,7 +906,7 @@ HError define_gamedata_location_checkall(String &data_path, String &startup_dir)
 		}
 	}
 
-#if defined (AGS_SEARCH_FOR_GAME_ON_LAUNCH)
+#if AGS_SEARCH_FOR_GAME_ON_LAUNCH
 	// No direct filepath provided, search in common locations.
 	data_path = search_for_game_data_file(startup_dir);
 	if (data_path.IsEmpty()) {
diff --git a/engines/ags/shared/core/platform.h b/engines/ags/shared/core/platform.h
index 25142e05f6..386e84e571 100644
--- a/engines/ags/shared/core/platform.h
+++ b/engines/ags/shared/core/platform.h
@@ -137,6 +137,16 @@ namespace AGS3 {
 #define AGS_PLATFORM_DEBUG  (0)
 #endif
 
+#define AGS_HAS_DIRECT3D (AGS_PLATFORM_OS_WINDOWS)
+#define AGS_HAS_OPENGL (AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_LINUX)
+#define AGS_OPENGL_ES2 (AGS_PLATFORM_OS_ANDROID)
+
+// Only allow searching around for game data on desktop systems;
+// otherwise use explicit argument either from program wrapper, command-line
+// or read from default config.
+#define AGS_SEARCH_FOR_GAME_ON_LAUNCH (AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX || AGS_PLATFORM_OS_MACOS)
+
+
 } // namespace AGS3
 
 #endif


Commit: b064647fb4a7b43d6afad74a6d35afff0aaff926
    https://github.com/scummvm/scummvm/commit/b064647fb4a7b43d6afad74a6d35afff0aaff926
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:06-07:00

Commit Message:
AGS: Removed unnecessary code

>From upstream f0951d4ec150f160e1ef727dac92bb5bd162dc48

Changed paths:
    engines/ags/engine/main/game_start.cpp


diff --git a/engines/ags/engine/main/game_start.cpp b/engines/ags/engine/main/game_start.cpp
index b6b7cb6416..a0bf38b5bc 100644
--- a/engines/ags/engine/main/game_start.cpp
+++ b/engines/ags/engine/main/game_start.cpp
@@ -103,27 +103,11 @@ void start_game() {
 	first_room_initialization();
 }
 
-void do_start_game() {
-	// only start if replay playback hasn't loaded a game
-	if (_G(displayed_room) < 0)
-		start_game();
-}
-
 void initialize_start_and_play_game(int override_start_room, int loadSaveGameOnStartup) {
 	//try { // BEGIN try for ALI3DEXception
 
 	set_cursor_mode(MODE_WALK);
 
-	if (_G(convert_16bit_bgr)) {
-		// Disable text as speech while displaying the warning message
-		// This happens if the user's graphics card does BGR order 16-bit colour
-		int oldalways = _GP(game).options[OPT_ALWAYSSPCH];
-		_GP(game).options[OPT_ALWAYSSPCH] = 0;
-		// PSP: This is normal. Don't show a warning.
-		//Display ("WARNING: AGS has detected that you have an incompatible graphics card for this _GP(game). You may experience colour problems during the _GP(game). Try running the game with \"--15bit\" command line parameter and see if that helps.[[Click the mouse to continue.");
-		_GP(game).options[OPT_ALWAYSSPCH] = oldalways;
-	}
-
 	::AGS::g_vm->setRandomNumberSeed(_GP(play).randseed);
 	if (override_start_room)
 		_G(playerchar)->room = override_start_room;
@@ -135,7 +119,9 @@ void initialize_start_and_play_game(int override_start_room, int loadSaveGameOnS
 
 	start_game_load_savegame_on_startup();
 
-	do_start_game();
+	// only start if not restored a save
+	if (_G(displayed_room) < 0)
+		start_game();
 
 	RunGameUntilAborted();
 


Commit: e584f41a4caf8eae1041267c77734a6211237665
    https://github.com/scummvm/scummvm/commit/e584f41a4caf8eae1041267c77734a6211237665
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:07-07:00

Commit Message:
AGS: fixed BufferedStream was not closing file handle on error

>From upstream 399371a7fafcb5560a2836186f23090acf92d263

Changed paths:
    engines/ags/shared/util/buffered_stream.cpp


diff --git a/engines/ags/shared/util/buffered_stream.cpp b/engines/ags/shared/util/buffered_stream.cpp
index e609cca905..71106716af 100644
--- a/engines/ags/shared/util/buffered_stream.cpp
+++ b/engines/ags/shared/util/buffered_stream.cpp
@@ -36,12 +36,17 @@ BufferedStream::BufferedStream(const String &file_name, FileOpenMode open_mode,
 		if (FileStream::Seek(0, kSeekEnd) == false)
 			error("Error determining stream end.");
 
-		_end = FileStream::GetPosition();
-		if (_end == -1)
-			error("Error determining stream end.");
+		_end = -1;
+		if (FileStream::Seek(0, kSeekEnd)) {
+			_end = FileStream::GetPosition();
+			if (!FileStream::Seek(0, kSeekBegin))
+				_end = -1;
+		}
 
-		if (FileStream::Seek(0, kSeekBegin) == false)
+		if (_end == -1) {
+			FileStream::Close();
 			error("Error determining stream end.");
+		}
 	}
 
 	_buffer.resize(0);


Commit: a9837a9039b2d003109620dac55fc8946eefea49
    https://github.com/scummvm/scummvm/commit/a9837a9039b2d003109620dac55fc8946eefea49
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:07-07:00

Commit Message:
AGS: removed FixSlashAfterToken, not necessary with ConcatPaths

>From upstream bda7710a06121129748e5f5a93916085f55e9f14

Changed paths:
    engines/ags/engine/ac/file.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/ac/path_helper.h


diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index 8625b3f9fd..b22fd4c951 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -227,30 +227,6 @@ String PathFromInstallDir(const String &path) {
 	return path;
 }
 
-// Tests if there is a special path token in the beginning of the given path;
-// if there is and there is no slash between token and the rest of the string,
-// then assigns new string that has such slash.
-// Returns TRUE if the new string was created, and FALSE if the path was good.
-bool FixSlashAfterToken(const String &path, const String &token, String &new_path) {
-	if (path.CompareLeft(token) == 0 && path.GetLength() > token.GetLength() &&
-	        path[token.GetLength()] != '/') {
-		new_path = Path::ConcatPaths(token, path.Mid(token.GetLength()));
-		return true;
-	}
-	return false;
-}
-
-String FixSlashAfterToken(const String &path) {
-	String fixed_path = path;
-	Path::FixupPath(fixed_path);
-	if (FixSlashAfterToken(fixed_path, GameInstallRootToken, fixed_path) ||
-	        FixSlashAfterToken(fixed_path, UserSavedgamesRootToken, fixed_path) ||
-	        FixSlashAfterToken(fixed_path, GameSavedgamesDirToken, fixed_path) ||
-	        FixSlashAfterToken(fixed_path, GameDataDirToken, fixed_path))
-		return fixed_path;
-	return path;
-}
-
 String PreparePathForWriting(const FSLocation &fsloc, const String &filename) {
 	if (Directory::CreateAllDirectories(fsloc.BaseDir, fsloc.FullDir))
 		return Path::ConcatPaths(fsloc.FullDir, filename);
@@ -318,23 +294,8 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 		debugC(::AGS::kDebugFilePath, "Full path detected");
 		return true;
 	}
-	/*
-	if (read_only) {
-		// For reading files, first try as a save file, then fall back
-		// in the game folder. This handles cases where some games like
-		// The Blackwell Legacy write to files in the game folder
-		rp.BaseDir = SAVE_FOLDER_PREFIX;
-		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
-			orig_sc_path.GetCStr());
-		rp.AltPath = orig_sc_path;
-	} else {
-		// For writing files, always use as save files
-		rp.BaseDir = SAVE_FOLDER_PREFIX;
-		rp.FullPath = String::FromFormat("%s%s", SAVE_FOLDER_PREFIX,
-			orig_sc_path.GetCStr());
-	}
-	*/
-	String sc_path = FixSlashAfterToken(orig_sc_path);
+
+	String sc_path = orig_sc_path;
 	FSLocation parent_dir;
 	String child_path;
 	String alt_path;
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 8dbb57be83..e8d8dd56a4 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -239,6 +239,7 @@ String get_save_game_path(int slotNum) {
 #endif
 }
 
+#if !AGS_PLATFORM_SCUMMVM
 // Convert a path possibly containing path tags into acceptable save path
 bool MakeSaveGameDir(const String &newFolder, ResolvedPath &rp) {
 	rp = ResolvedPath();
@@ -280,6 +281,7 @@ bool MakeSaveGameDir(const String &newFolder, ResolvedPath &rp) {
 	rp.FullPath = newSaveGameDir;
 	return true;
 }
+#endif
 
 bool SetCustomSaveParent(const String &path) {
 	if (SetSaveGameDirectoryPath(path, true)) {
diff --git a/engines/ags/engine/ac/path_helper.h b/engines/ags/engine/ac/path_helper.h
index 7475e8cdec..907c023d43 100644
--- a/engines/ags/engine/ac/path_helper.h
+++ b/engines/ags/engine/ac/path_helper.h
@@ -51,10 +51,6 @@ void FixupFilename(char *filename);
 // Tests the input path, if it's an absolute path then returns it unchanged;
 // if it's a relative path then resolves it into absolute, using install dir as a base.
 String PathFromInstallDir(const String &path);
-// Checks if there is a slash after special token in the beginning of the
-// file path, and adds one if it is missing. If no token is found, string is
-// returned unchanged.
-String FixSlashAfterToken(const String &path);
 
 // FSLocation describes a file system location defined by two parts:
 // a secure path that engine does not own, and sub-path that it owns.


Commit: a95ec92e6cce7d247e07d50a6477d284414cec50
    https://github.com/scummvm/scummvm/commit/a95ec92e6cce7d247e07d50a6477d284414cec50
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:08-07:00

Commit Message:
AGS: Added comments for WalkBehindMethodEnum

>From upstream a917450c19aae2d9047e50d6267bf2744ab2e5dc

Changed paths:
    engines/ags/engine/ac/walk_behind.h


diff --git a/engines/ags/engine/ac/walk_behind.h b/engines/ags/engine/ac/walk_behind.h
index 0df82ba6ef..8f8a7436dd 100644
--- a/engines/ags/engine/ac/walk_behind.h
+++ b/engines/ags/engine/ac/walk_behind.h
@@ -25,6 +25,16 @@
 
 namespace AGS3 {
 
+// A method of rendering walkbehinds on screen:
+// DrawAsSeparateSprite - draws whole walkbehind as a sprite; this
+//     method is most simple and is optimal for 3D renderers.
+// DrawOverCharSprite and DrawAsSeparateCharSprite - are alternatives
+//     optimized for software render.
+// DrawOverCharSprite - turns parts of the character and object sprites
+//     transparent when they are covered by walkbehind (walkbehind itself
+//     is not drawn separately in this case).
+// DrawAsSeparateCharSprite - draws smaller *parts* of walkbehind as
+//     separate sprites, only ones that cover characters or objects.
 enum WalkBehindMethodEnum {
 	DrawOverCharSprite,
 	DrawAsSeparateSprite,


Commit: 8278e9fa521cbed91fef356991b9e0cd9e30a8f2
    https://github.com/scummvm/scummvm/commit/8278e9fa521cbed91fef356991b9e0cd9e30a8f2
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:08-07:00

Commit Message:
AGS: Moved PlaneScaling to Shared

>From upstream 080226c6b1c1a9b7ae913dedd35a2022a3ce1940

Changed paths:
  A engines/ags/shared/util/scaling.h
  R engines/ags/engine/util/scaling.h
    engines/ags/engine/ac/draw_software.cpp
    engines/ags/engine/ac/draw_software.h
    engines/ags/engine/game/viewport.h
    engines/ags/engine/gfx/gfx_driver_base.h
    engines/ags/engine/gfx/gfxfilter_scaling.h
    engines/ags/engine/main/graphics_mode.h
    engines/ags/globals.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/draw_software.cpp b/engines/ags/engine/ac/draw_software.cpp
index 7bec6d6c5d..d7aa4dfd66 100644
--- a/engines/ags/engine/ac/draw_software.cpp
+++ b/engines/ags/engine/ac/draw_software.cpp
@@ -49,7 +49,7 @@
 #include "ags/lib/std/vector.h"
 #include "ags/engine/ac/draw_software.h"
 #include "ags/shared/gfx/bitmap.h"
-#include "ags/engine/util/scaling.h"
+#include "ags/shared/util/scaling.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -354,7 +354,7 @@ void update_invalid_region(Bitmap *ds, color_t fill_color, const DirtyRects &rec
 		const std::vector<IRRow> &dirtyRow = rects.DirtyRows;
 		const int surf_height = rects.SurfaceSize.Height;
 		{
-			const PlaneScaling &tf = rects.Room2Screen;
+			const AGS::Shared::PlaneScaling &tf = rects.Room2Screen;
 			for (int i = 0, rowsInOne = 1; i < surf_height; i += rowsInOne, rowsInOne = 1) {
 				// if there are rows with identical masks, do them all in one go
 				// TODO: what is this for? may this be done at the invalidate_rect merge step?
diff --git a/engines/ags/engine/ac/draw_software.h b/engines/ags/engine/ac/draw_software.h
index adda8e1e1c..02b2100c21 100644
--- a/engines/ags/engine/ac/draw_software.h
+++ b/engines/ags/engine/ac/draw_software.h
@@ -33,11 +33,11 @@
 #include "ags/shared/gfx/bitmap.h"
 #include "ags/engine/gfx/ddb.h"
 #include "ags/shared/util/geometry.h"
-#include "ags/engine/util/scaling.h"
+#include "ags/shared/util/scaling.h"
 
 namespace AGS3 {
 
-using AGS::Engine::PlaneScaling;
+using AGS::Shared::PlaneScaling;
 
 // TODO: choose these values depending on game resolution?
 #define MAXDIRTYREGIONS 25
diff --git a/engines/ags/engine/game/viewport.h b/engines/ags/engine/game/viewport.h
index b99f7a2095..9bb9cc993e 100644
--- a/engines/ags/engine/game/viewport.h
+++ b/engines/ags/engine/game/viewport.h
@@ -32,7 +32,7 @@
 #include "ags/lib/std/memory.h"
 #include "ags/lib/std/vector.h"
 #include "ags/shared/util/geometry.h"
-#include "ags/engine/util/scaling.h"
+#include "ags/shared/util/scaling.h"
 
 namespace AGS3 {
 
@@ -139,7 +139,7 @@ public:
 		return _position;
 	}
 	// Returns viewport's room-to-screen transformation
-	inline const AGS::Engine::PlaneScaling &GetTransform() const {
+	inline const AGS::Shared::PlaneScaling &GetTransform() const {
 		return _transform;
 	}
 	// Set viewport's rectangle on screen
@@ -210,7 +210,7 @@ private:
 	// Coordinate tranform between camera and viewport
 	// TODO: need to add rotate conversion to let script API support that;
 	// (maybe use full 3D matrix for that)
-	AGS::Engine::PlaneScaling _transform;
+	AGS::Shared::PlaneScaling _transform;
 	// Linked camera reference
 	CameraRef _camera;
 	bool _visible = true;
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index a3b921f9db..4cc6eb6dba 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -32,13 +32,14 @@
 #include "ags/lib/std/vector.h"
 #include "ags/engine/gfx/ddb.h"
 #include "ags/engine/gfx/graphics_driver.h"
-#include "ags/engine/util/scaling.h"
+#include "ags/shared/util/scaling.h"
 
 namespace AGS3 {
 namespace AGS {
 namespace Engine {
 
 using Shared::Bitmap;
+using Shared::PlaneScaling;
 
 // Sprite batch, defines viewport and an optional model transformation for the list of sprites
 struct SpriteBatchDesc {
diff --git a/engines/ags/engine/gfx/gfxfilter_scaling.h b/engines/ags/engine/gfx/gfxfilter_scaling.h
index aef99c081a..c4e12b0a9a 100644
--- a/engines/ags/engine/gfx/gfxfilter_scaling.h
+++ b/engines/ags/engine/gfx/gfxfilter_scaling.h
@@ -30,12 +30,14 @@
 #define AGS_ENGINE_GFX_SCALING_GFX_FILTER_H
 
 #include "ags/engine/gfx/gfxfilter.h"
-#include "ags/engine/util/scaling.h"
+#include "ags/shared/util/scaling.h"
 
 namespace AGS3 {
 namespace AGS {
 namespace Engine {
 
+using AGS::Shared::PlaneScaling;
+
 class ScalingGfxFilter : public IGfxFilter {
 public:
 	bool Initialize(const int color_depth, String &err_str) override;
diff --git a/engines/ags/engine/main/graphics_mode.h b/engines/ags/engine/main/graphics_mode.h
index ac35fc9810..0cd6a45a5e 100644
--- a/engines/ags/engine/main/graphics_mode.h
+++ b/engines/ags/engine/main/graphics_mode.h
@@ -25,7 +25,7 @@
 
 #include "ags/engine/gfx/gfx_defines.h"
 #include "ags/shared/util/geometry.h"
-#include "ags/engine/util/scaling.h"
+#include "ags/shared/util/scaling.h"
 #include "ags/shared/util/string.h"
 
 namespace AGS3 {
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 29de76c954..2e44efb072 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -245,7 +245,7 @@ Globals::Globals() {
 	_SavedFullscreenSetting = new ActiveDisplaySetting();
 	_SavedWindowedSetting = new ActiveDisplaySetting();
 	_CurFrameSetup = new GameFrameSetup();
-	_GameScaling = new AGS::Engine::PlaneScaling();
+	_GameScaling = new AGS::Shared::PlaneScaling();
 
 	// gui_button.cpp globals
 	_guibuts = new std::vector<AGS::Shared::GUIButton>();
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 3a9087e256..bc27fc8dba 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -68,6 +68,7 @@ class GUIListBox;
 class GUISlider;
 class GUITextBox;
 struct InteractionVariable;
+struct PlaneScaling;
 class RoomStruct;
 
 } // namespace Shared
@@ -81,7 +82,6 @@ class IGfxDriverFactory;
 class IGraphicsDriver;
 class LogFile;
 class MessageBuffer;
-struct PlaneScaling;
 
 } // namespace Engine
 } // namespace AGS
@@ -871,7 +871,7 @@ public:
 	// Current frame scaling setup
 	GameFrameSetup *_CurFrameSetup;
 	// The game-to-screen transformation
-	AGS::Engine::PlaneScaling *_GameScaling;
+	AGS::Shared::PlaneScaling *_GameScaling;
 
 	/**@}*/
 
diff --git a/engines/ags/engine/util/scaling.h b/engines/ags/shared/util/scaling.h
similarity index 97%
rename from engines/ags/engine/util/scaling.h
rename to engines/ags/shared/util/scaling.h
index d79e8a92df..c00f8076fa 100644
--- a/engines/ags/engine/util/scaling.h
+++ b/engines/ags/shared/util/scaling.h
@@ -29,15 +29,15 @@
 //
 //=============================================================================
 
-#ifndef AGS_ENGINE_UTIL_SCALING_H
-#define AGS_ENGINE_UTIL_SCALING_H
+#ifndef AGS_SHARED_UTIL_SCALING_H
+#define AGS_SHARED_UTIL_SCALING_H
 
 #include "ags/shared/core/types.h"
 #include "ags/shared/util/geometry.h"
 
 namespace AGS3 {
 namespace AGS {
-namespace Engine {
+namespace Shared {
 
 class AxisScaling {
 public:
@@ -155,7 +155,7 @@ struct PlaneScaling {
 	}
 };
 
-} // namespace Engine
+} // namespace Shared
 } // namespace AGS
 } // namespace AGS3
 


Commit: 7a3d9aa32b035add7128516bef79887a4d757921
    https://github.com/scummvm/scummvm/commit/7a3d9aa32b035add7128516bef79887a4d757921
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:09-07:00

Commit Message:
AGS: Removed deprecated comments

Changed paths:
    engines/ags/engine/main/main.cpp


diff --git a/engines/ags/engine/main/main.cpp b/engines/ags/engine/main/main.cpp
index b4251a7cc0..b1a81ac888 100644
--- a/engines/ags/engine/main/main.cpp
+++ b/engines/ags/engine/main/main.cpp
@@ -20,16 +20,6 @@
  *
  */
 
-//
-// Entry point of the application here.
-//
-//
-// For Windows main() function is really called _mangled_main and is called
-// not by system, but from insides of allegro library.
-// (See allegro\platform\alwin.h)
-// What about other platforms?
-//
-
 #include "ags/shared/core/platform.h"
 #define AGS_PLATFORM_DEFINES_PSP_VARS (AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID)
 #include "ags/lib/std/set.h"


Commit: 9206ecbe4b8263e2a783705b1c542a4d548128e0
    https://github.com/scummvm/scummvm/commit/9206ecbe4b8263e2a783705b1c542a4d548128e0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:09-07:00

Commit Message:
AGS: Removed mention of NO_MP3_PLAYER

>From upstream d1366a50e4a07626a15e0d9375aba8f58f5fc96e

Changed paths:
    engines/ags/shared/core/def_version.h


diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index a668203265..51945dc3ff 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -23,16 +23,12 @@
 #ifndef AGS_SHARED_CORE_DEFVERSION_H
 #define AGS_SHARED_CORE_DEFVERSION_H
 
-#define ACI_VERSION_STR      "3.6.0.2"
+#define ACI_VERSION_STR      "3.6.0.3"
 #if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF  3,6,0,2
+#define ACI_VERSION_MSRC_DEF  3,6,0,3
 #endif
 
-#ifdef NO_MP3_PLAYER
-#define SPECIAL_VERSION "NMP"
-#else
 #define SPECIAL_VERSION ""
-#endif
 
 #define ACI_COPYRIGHT_YEARS "2011-2021"
 


Commit: 19808ce0c82078362c719dbf4bdb51ab9ddc842e
    https://github.com/scummvm/scummvm/commit/19808ce0c82078362c719dbf4bdb51ab9ddc842e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:10-07:00

Commit Message:
AGS: Fixed comment to room_file.h

>From upstream 09a3d3419d65903dc10cbd276e426788faf0808e

Changed paths:
    engines/ags/shared/game/room_file.h


diff --git a/engines/ags/shared/game/room_file.h b/engines/ags/shared/game/room_file.h
index c7eae1cf37..ae9c4bbdb6 100644
--- a/engines/ags/shared/game/room_file.h
+++ b/engines/ags/shared/game/room_file.h
@@ -22,9 +22,9 @@
 
 //=============================================================================
 //
-// This unit provides functions for reading main game file into appropriate
-// data structures. Main game file contains general game data, such as global
-// options, lists of static game entities and compiled scripts modules.
+// This unit provides functions for reading compiled room file (CRM)
+// into the RoomStruct structure, as well as extracting separate components,
+// such as room scripts.
 //
 //=============================================================================
 


Commit: 1028fc40eb37dd1cb898660f0ffc7b63e0b61fd4
    https://github.com/scummvm/scummvm/commit/1028fc40eb37dd1cb898660f0ffc7b63e0b61fd4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:10-07:00

Commit Message:
AGS: Split room_file.cpp to have generic read functions separate

>From upstream 6bc0bc35afb1e6510cd70ddaead768ff1af643e8

Changed paths:
  A engines/ags/shared/game/room_file_base.cpp
    engines/ags/module.mk
    engines/ags/shared/game/room_file.cpp
    engines/ags/shared/game/room_file.h


diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index f58017b88b..2cff913501 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -53,6 +53,7 @@ MODULE_OBJS = \
 	shared/game/interactions.o \
 	shared/game/main_game_file.o \
 	shared/game/room_file.o \
+	shared/game/room_file_base.o \
 	shared/game/room_file_deprecated.o \
 	shared/game/room_struct.o \
 	shared/gfx/allegro_bitmap.o \
diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index 7276d4144e..7483eaf852 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -50,62 +50,6 @@ namespace AGS3 {
 namespace AGS {
 namespace Shared {
 
-RoomDataSource::RoomDataSource()
-	: DataVersion(kRoomVersion_Undefined) {
-}
-
-String GetRoomFileErrorText(RoomFileErrorType err) {
-	switch (err) {
-	case kRoomFileErr_NoError:
-		return "No error.";
-	case kRoomFileErr_FileOpenFailed:
-		return "Room file was not found or could not be opened.";
-	case kRoomFileErr_FormatNotSupported:
-		return "Format version not supported.";
-	case kRoomFileErr_UnexpectedEOF:
-		return "Unexpected end of file.";
-	case kRoomFileErr_UnknownBlockType:
-		return "Unknown block type.";
-	case kRoomFileErr_OldBlockNotSupported:
-		return "Block type is too old and not supported by this version of the engine.";
-	case kRoomFileErr_BlockDataOverlapping:
-		return "Block data overlapping.";
-	case kRoomFileErr_IncompatibleEngine:
-		return "This engine cannot handle requested room content.";
-	case kRoomFileErr_ScriptLoadFailed:
-		return "Script load failed.";
-	case kRoomFileErr_InconsistentData:
-		return "Inconsistent room data, or file is corrupted.";
-	case kRoomFileErr_PropertiesBlockFormat:
-		return "Unknown format of the custom properties block.";
-	case kRoomFileErr_InvalidPropertyValues:
-		return "Errors encountered when reading custom properties.";
-	case kRoomFileErr_BlockNotFound:
-		return "Required block was not found.";
-	}
-	return "Unknown error.";
-}
-
-// Read room data header and check that we support this format
-static HRoomFileError OpenRoomFileBase(Stream *in, RoomDataSource &src) {
-	src.DataVersion = (RoomFileVersion)in->ReadInt16();
-	if (src.DataVersion < kRoomVersion_250b || src.DataVersion > kRoomVersion_Current)
-		return new RoomFileError(kRoomFileErr_FormatNotSupported, String::FromFormat("Required format version: %d, supported %d - %d", src.DataVersion, kRoomVersion_250b, kRoomVersion_Current));
-	return HRoomFileError::None();
-}
-
-HRoomFileError OpenRoomFile(const String &filename, RoomDataSource &src) {
-	// Cleanup source struct
-	src = RoomDataSource();
-	// Try to open room file
-	Stream *in = File::OpenFileRead(filename);
-	if (in == nullptr)
-		return new RoomFileError(kRoomFileErr_FileOpenFailed, String::FromFormat("Filename: %s.", filename.GetCStr()));
-	src.Filename = filename;
-	src.InputStream.reset(in);
-	return OpenRoomFileBase(in, src);
-}
-
 HRoomFileError OpenRoomFileFromAsset(const String &filename, RoomDataSource &src) {
 	// Cleanup source struct
 	src = RoomDataSource();
@@ -115,57 +59,7 @@ HRoomFileError OpenRoomFileFromAsset(const String &filename, RoomDataSource &src
 		return new RoomFileError(kRoomFileErr_FileOpenFailed, String::FromFormat("Filename: %s.", filename.GetCStr()));
 	src.Filename = filename;
 	src.InputStream.reset(in);
-	return OpenRoomFileBase(in, src);
-}
-
-
-enum RoomFileBlock {
-	kRoomFblk_None = 0,
-	// Main room data
-	kRoomFblk_Main = 1,
-	// Room script text source (was present in older room formats)
-	kRoomFblk_Script = 2,
-	// Old versions of compiled script (no longer supported)
-	kRoomFblk_CompScript = 3,
-	kRoomFblk_CompScript2 = 4,
-	// Names of the room objects
-	kRoomFblk_ObjectNames = 5,
-	// Secondary room backgrounds
-	kRoomFblk_AnimBg = 6,
-	// Contemporary compiled script
-	kRoomFblk_CompScript3 = 7,
-	// Custom properties
-	kRoomFblk_Properties = 8,
-	// Script names of the room objects
-	kRoomFblk_ObjectScNames = 9,
-	// End of room data tag
-	kRoomFile_EOF = 0xFF
-};
-
-String GetRoomBlockName(RoomFileBlock id) {
-	switch (id) {
-	case kRoomFblk_Main:
-		return "Main";
-	case kRoomFblk_Script:
-		return "TextScript";
-	case kRoomFblk_CompScript:
-		return "CompScript";
-	case kRoomFblk_CompScript2:
-		return "CompScript2";
-	case kRoomFblk_ObjectNames:
-		return "ObjNames";
-	case kRoomFblk_AnimBg:
-		return "AnimBg";
-	case kRoomFblk_CompScript3:
-		return "CompScript3";
-	case kRoomFblk_Properties:
-		return "Properties";
-	case kRoomFblk_ObjectScNames:
-		return "ObjScNames";
-	default:
-		break;
-	}
-	return "unknown";
+	return ReadRoomHeader(src);
 }
 
 void ReadRoomObject(RoomObjectInfo &obj, Stream *in) {
@@ -561,32 +455,6 @@ HRoomFileError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block,
 	                         String::FromFormat("Type: %s", ext_id.GetCStr()));
 }
 
-
-static HRoomFileError OpenNextBlock(Stream *in, RoomFileVersion data_ver, RoomFileBlock &block_id, String &ext_id, soff_t &block_len) {
-	// The block meta format is shared with the main game file extensions
-	//    - 1 byte - an old-style unsigned numeric ID:
-	//               where 0 would indicate following string ID,
-	//               and 0xFF indicates end of extension list.
-	//    - 16 bytes - string ID of an extension (if numeric ID is 0).
-	//    - 4 or 8 bytes - length of extension data, in bytes (size depends on format version).
-	int b = in->ReadByte();
-	if (b < 0)
-		return new RoomFileError(kRoomFileErr_UnexpectedEOF);
-
-	block_id = (RoomFileBlock)b;
-	if (block_id == kRoomFile_EOF)
-		return HRoomFileError::None(); // end of list
-
-	if (block_id > 0) { // old-style block identified by a numeric id
-		ext_id = GetRoomBlockName(block_id);
-		block_len = data_ver < kRoomVersion_350 ? in->ReadInt32() : in->ReadInt64();
-	} else { // new style block identified by a string id
-		ext_id = String::FromStreamCount(in, 16);
-		block_len = in->ReadInt64();
-	}
-	return HRoomFileError::None();
-}
-
 HRoomFileError ReadRoomData(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	room->DataVersion = data_ver;
 
@@ -599,7 +467,7 @@ HRoomFileError ReadRoomData(RoomStruct *room, Stream *in, RoomFileVersion data_v
 		RoomFileBlock block_id;
 		String ext_id;
 		soff_t block_len;
-		HRoomFileError err = OpenNextBlock(in, data_ver, block_id, ext_id, block_len);
+		HRoomFileError err = OpenNextRoomBlock(in, data_ver, block_id, ext_id, block_len);
 		if (!err)
 			return err;
 		if (ext_id.IsEmpty())
@@ -760,7 +628,7 @@ HRoomFileError ExtractScriptText(String &script, Stream *in, RoomFileVersion dat
 		RoomFileBlock block_id;
 		String ext_id;
 		soff_t block_len;
-		err = OpenNextBlock(in, data_ver, block_id, ext_id, block_len);
+		err = OpenNextRoomBlock(in, data_ver, block_id, ext_id, block_len);
 		if (!err)
 			return err;
 		if (ext_id.IsEmpty())
@@ -780,40 +648,6 @@ HRoomFileError ExtractScriptText(String &script, Stream *in, RoomFileVersion dat
 	return new RoomFileError(kRoomFileErr_BlockNotFound);
 }
 
-
-// Type of function that writes single room block.
-typedef void(*PfnWriteBlock)(const RoomStruct *room, Stream *out);
-// Generic function that saves a block and automatically adds its size into header
-void WriteBlock(const RoomStruct *room, RoomFileBlock block, const String &ext_id, PfnWriteBlock writer, Stream *out) {
-	// Write block's header
-	out->WriteByte(block);
-	if (block == kRoomFblk_None) // new-style string id
-		ext_id.WriteCount(out, 16);
-	soff_t sz_at = out->GetPosition();
-	out->WriteInt64(0); // block size placeholder
-	// Call writer to save actual block contents
-	writer(room, out);
-
-	// Now calculate the block's size...
-	soff_t end_at = out->GetPosition();
-	soff_t block_size = (end_at - sz_at) - sizeof(int64_t);
-	// ...return back and write block's size in the placeholder
-	out->Seek(sz_at, Shared::kSeekBegin);
-	out->WriteInt64(block_size);
-	// ...and get back to the end of the file
-	out->Seek(0, Shared::kSeekEnd);
-}
-
-// Helper for new-style blocks with string id
-void WriteBlock(const RoomStruct *room, const String &ext_id, PfnWriteBlock writer, Stream *out) {
-	WriteBlock(room, kRoomFblk_None, ext_id, writer, out);
-}
-
-// Helper for old-style blocks with only numeric id
-void WriteBlock(const RoomStruct *room, RoomFileBlock block, PfnWriteBlock writer, Stream *out) {
-	WriteBlock(room, block, String(), writer, out);
-}
-
 void WriteInteractionScripts(const InteractionScripts *interactions, Stream *out) {
 	out->WriteInt32(interactions->ScriptFuncNames.size());
 	for (size_t i = 0; i < interactions->ScriptFuncNames.size(); ++i)
@@ -953,20 +787,20 @@ HRoomFileError WriteRoomData(const RoomStruct *room, Stream *out, RoomFileVersio
 	// Header
 	out->WriteInt16(data_ver);
 	// Main data
-	WriteBlock(room, kRoomFblk_Main, WriteMainBlock, out);
+	WriteRoomBlock(room, kRoomFblk_Main, WriteMainBlock, out);
 	// Compiled script
 	if (room->CompiledScript)
-		WriteBlock(room, kRoomFblk_CompScript3, WriteCompSc3Block, out);
+		WriteRoomBlock(room, kRoomFblk_CompScript3, WriteCompSc3Block, out);
 	// Object names
 	if (room->ObjectCount > 0) {
-		WriteBlock(room, kRoomFblk_ObjectNames, WriteObjNamesBlock, out);
-		WriteBlock(room, kRoomFblk_ObjectScNames, WriteObjScNamesBlock, out);
+		WriteRoomBlock(room, kRoomFblk_ObjectNames, WriteObjNamesBlock, out);
+		WriteRoomBlock(room, kRoomFblk_ObjectScNames, WriteObjScNamesBlock, out);
 	}
 	// Secondary background frames
 	if (room->BgFrameCount > 1)
-		WriteBlock(room, kRoomFblk_AnimBg, WriteAnimBgBlock, out);
+		WriteRoomBlock(room, kRoomFblk_AnimBg, WriteAnimBgBlock, out);
 	// Custom properties
-	WriteBlock(room, kRoomFblk_Properties, WritePropertiesBlock, out);
+	WriteRoomBlock(room, kRoomFblk_Properties, WritePropertiesBlock, out);
 
 	// Write end of room file
 	out->WriteByte(kRoomFile_EOF);
diff --git a/engines/ags/shared/game/room_file.h b/engines/ags/shared/game/room_file.h
index ae9c4bbdb6..b9ce7d601c 100644
--- a/engines/ags/shared/game/room_file.h
+++ b/engines/ags/shared/game/room_file.h
@@ -63,7 +63,31 @@ enum RoomFileErrorType {
 	kRoomFileErr_BlockNotFound
 };
 
+enum RoomFileBlock {
+	kRoomFblk_None = 0,
+	// Main room data
+	kRoomFblk_Main = 1,
+	// Room script text source (was present in older room formats)
+	kRoomFblk_Script = 2,
+	// Old versions of compiled script (no longer supported)
+	kRoomFblk_CompScript = 3,
+	kRoomFblk_CompScript2 = 4,
+	// Names of the room objects
+	kRoomFblk_ObjectNames = 5,
+	// Secondary room backgrounds
+	kRoomFblk_AnimBg = 6,
+	// Contemporary compiled script
+	kRoomFblk_CompScript3 = 7,
+	// Custom properties
+	kRoomFblk_Properties = 8,
+	// Script names of the room objects
+	kRoomFblk_ObjectScNames = 9,
+	// End of room data tag
+	kRoomFile_EOF = 0xFF
+};
+
 String GetRoomFileErrorText(RoomFileErrorType err);
+String GetRoomBlockName(RoomFileBlock id);
 
 typedef TypedCodeError<RoomFileErrorType, GetRoomFileErrorText> RoomFileError;
 typedef ErrorHandle<RoomFileError> HRoomFileError;
@@ -74,7 +98,6 @@ typedef std::unique_ptr<Stream> UStream;
 #endif
 
 
-
 // RoomDataSource defines a successfully opened room file
 struct RoomDataSource {
 	// Name of the asset file
@@ -99,9 +122,21 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g
 // Extracts text script from the room file, if it's available.
 // Historically, text sources were kept inside packed room files before AGS 3.*.
 HRoomFileError ExtractScriptText(String &script, Stream *in, RoomFileVersion data_ver);
-
+// Writes all room data to the stream
 HRoomFileError WriteRoomData(const RoomStruct *room, Stream *out, RoomFileVersion data_ver);
 
+// Reads room data header using stream assigned to RoomDataSource;
+// tests and saves its format index if successful
+HRoomFileError ReadRoomHeader(RoomDataSource &src);
+// Opens next room block from the stream, fills in its identifier and length on success
+HRoomFileError OpenNextRoomBlock(Stream *in, RoomFileVersion data_ver, RoomFileBlock &block_id, String &ext_id, soff_t &block_len);
+// Type of function that writes single room block.
+typedef void(*PfnWriteRoomBlock)(const RoomStruct *room, Stream *out);
+// Writes room block with a new-style string id
+void WriteRoomBlock(const RoomStruct *room, const String &ext_id, PfnWriteRoomBlock writer, Stream *out);
+// Writes room block with a old-style numeric id
+void WriteRoomBlock(const RoomStruct *room, RoomFileBlock block, PfnWriteRoomBlock writer, Stream *out);
+
 } // namespace Shared
 } // namespace AGS
 } // namespace AGS3
diff --git a/engines/ags/shared/game/room_file_base.cpp b/engines/ags/shared/game/room_file_base.cpp
new file mode 100644
index 0000000000..f934131829
--- /dev/null
+++ b/engines/ags/shared/game/room_file_base.cpp
@@ -0,0 +1,160 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/shared/game/room_file.h"
+#include "ags/shared/util/file.h"
+#include "ags/globals.h"
+
+namespace AGS3 {
+namespace AGS {
+namespace Shared {
+
+RoomDataSource::RoomDataSource()
+	: DataVersion(kRoomVersion_Undefined) {
+}
+
+String GetRoomFileErrorText(RoomFileErrorType err) {
+	switch (err) {
+	case kRoomFileErr_NoError:
+		return "No error.";
+	case kRoomFileErr_FileOpenFailed:
+		return "Room file was not found or could not be opened.";
+	case kRoomFileErr_FormatNotSupported:
+		return "Format version not supported.";
+	case kRoomFileErr_UnexpectedEOF:
+		return "Unexpected end of file.";
+	case kRoomFileErr_UnknownBlockType:
+		return "Unknown block type.";
+	case kRoomFileErr_OldBlockNotSupported:
+		return "Block type is too old and not supported by this version of the engine.";
+	case kRoomFileErr_BlockDataOverlapping:
+		return "Block data overlapping.";
+	case kRoomFileErr_IncompatibleEngine:
+		return "This engine cannot handle requested room content.";
+	case kRoomFileErr_ScriptLoadFailed:
+		return "Script load failed.";
+	case kRoomFileErr_InconsistentData:
+		return "Inconsistent room data, or file is corrupted.";
+	case kRoomFileErr_PropertiesBlockFormat:
+		return "Unknown format of the custom properties block.";
+	case kRoomFileErr_InvalidPropertyValues:
+		return "Errors encountered when reading custom properties.";
+	case kRoomFileErr_BlockNotFound:
+		return "Required block was not found.";
+	}
+	return "Unknown error.";
+}
+
+HRoomFileError OpenRoomFile(const String &filename, RoomDataSource &src) {
+	// Cleanup source struct
+	src = RoomDataSource();
+	// Try to open room file
+	Stream *in = File::OpenFileRead(filename);
+	if (in == nullptr)
+		return new RoomFileError(kRoomFileErr_FileOpenFailed, String::FromFormat("Filename: %s.", filename.GetCStr()));
+	src.Filename = filename;
+	src.InputStream.reset(in);
+	return ReadRoomHeader(src);
+}
+
+// Read room data header and check that we support this format
+HRoomFileError ReadRoomHeader(RoomDataSource &src) {
+	src.DataVersion = (RoomFileVersion)src.InputStream->ReadInt16();
+	if (src.DataVersion < kRoomVersion_250b || src.DataVersion > kRoomVersion_Current)
+		return new RoomFileError(kRoomFileErr_FormatNotSupported, String::FromFormat("Required format version: %d, supported %d - %d", src.DataVersion, kRoomVersion_250b, kRoomVersion_Current));
+	return HRoomFileError::None();
+}
+
+String GetRoomBlockName(RoomFileBlock id) {
+	switch (id) {
+	case kRoomFblk_Main: return "Main";
+	case kRoomFblk_Script: return "TextScript";
+	case kRoomFblk_CompScript: return "CompScript";
+	case kRoomFblk_CompScript2: return "CompScript2";
+	case kRoomFblk_ObjectNames: return "ObjNames";
+	case kRoomFblk_AnimBg: return "AnimBg";
+	case kRoomFblk_CompScript3: return "CompScript3";
+	case kRoomFblk_Properties: return "Properties";
+	case kRoomFblk_ObjectScNames: return "ObjScNames";
+	}
+	return "unknown";
+}
+
+HRoomFileError OpenNextRoomBlock(Stream *in, RoomFileVersion data_ver, RoomFileBlock &block_id, String &ext_id, soff_t &block_len) {
+	// The block meta format is shared with the main game file extensions
+	//    - 1 byte - an old-style unsigned numeric ID:
+	//               where 0 would indicate following string ID,
+	//               and 0xFF indicates end of extension list.
+	//    - 16 bytes - string ID of an extension (if numeric ID is 0).
+	//    - 4 or 8 bytes - length of extension data, in bytes (size depends on format version).
+	int b = in->ReadByte();
+	if (b < 0)
+		return new RoomFileError(kRoomFileErr_UnexpectedEOF);
+
+	block_id = (RoomFileBlock)b;
+	if (block_id == kRoomFile_EOF)
+		return HRoomFileError::None(); // end of list
+
+	if (block_id > 0) { // old-style block identified by a numeric id
+		ext_id = GetRoomBlockName(block_id);
+		block_len = data_ver < kRoomVersion_350 ? in->ReadInt32() : in->ReadInt64();
+	} else { // new style block identified by a string id
+		ext_id = String::FromStreamCount(in, 16);
+		block_len = in->ReadInt64();
+	}
+	return HRoomFileError::None();
+}
+
+// Generic function that saves a block and automatically adds its size into header
+static void WriteRoomBlock(const RoomStruct *room, RoomFileBlock block, const String &ext_id, PfnWriteRoomBlock writer, Stream *out) {
+	// Write block's header
+	out->WriteByte(block);
+	if (block == kRoomFblk_None) // new-style string id
+		ext_id.WriteCount(out, 16);
+	soff_t sz_at = out->GetPosition();
+	out->WriteInt64(0); // block size placeholder
+						// Call writer to save actual block contents
+	writer(room, out);
+
+	// Now calculate the block's size...
+	soff_t end_at = out->GetPosition();
+	soff_t block_size = (end_at - sz_at) - sizeof(int64_t);
+	// ...return back and write block's size in the placeholder
+	out->Seek(sz_at, Shared::kSeekBegin);
+	out->WriteInt64(block_size);
+	// ...and get back to the end of the file
+	out->Seek(0, Shared::kSeekEnd);
+}
+
+// Helper for new-style blocks with string id
+void WriteRoomBlock(const RoomStruct *room, const String &ext_id, PfnWriteRoomBlock writer, Stream *out) {
+	WriteRoomBlock(room, kRoomFblk_None, ext_id, writer, out);
+}
+
+// Helper for old-style blocks with only numeric id
+void WriteRoomBlock(const RoomStruct *room, RoomFileBlock block, PfnWriteRoomBlock writer, Stream *out) {
+	WriteRoomBlock(room, block, String(), writer, out);
+}
+
+} // namespace Shared
+} // namespace AGS
+} // namespace AGS3


Commit: 902521824d43515d933b5d701e174ea2ff4ef9c7
    https://github.com/scummvm/scummvm/commit/902521824d43515d933b5d701e174ea2ff4ef9c7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:10-07:00

Commit Message:
AGS: Picked out ReadRoomData() that runs a callback for each block

>From upstream ea513b91d29b460a85e006300e1e1e1df589b004

Changed paths:
    engines/ags/shared/game/room_file.cpp
    engines/ags/shared/game/room_file.h
    engines/ags/shared/game/room_file_base.cpp


diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index 7483eaf852..44cb259438 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -136,8 +136,8 @@ HRoomFileError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_
 	if (polypoint_areas > 0)
 		return new RoomFileError(kRoomFileErr_IncompatibleEngine, "Legacy poly-point areas are no longer supported.");
 	/* NOTE: implementation hidden in room_file_deprecated.cpp
-	    for (size_t i = 0; i < polypoint_areas; ++i)
-	        wallpoints[i].Read(in);
+		for (size_t i = 0; i < polypoint_areas; ++i)
+			wallpoints[i].Read(in);
 	*/
 
 	update_polled_stuff_if_runtime();
@@ -268,7 +268,7 @@ HRoomFileError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_
 		if (fullanim_count > 0)
 			return new RoomFileError(kRoomFileErr_IncompatibleEngine, "Room animations are no longer supported.");
 		/* NOTE: implementation hidden in room_file_deprecated.cpp
-		    in->ReadArray(&fullanims[0], sizeof(FullAnimation), fullanim_count);
+			in->ReadArray(&fullanims[0], sizeof(FullAnimation), fullanim_count);
 		*/
 	}
 
@@ -277,7 +277,7 @@ HRoomFileError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_
 	if ((data_ver >= kRoomVersion_pre114_4) && (data_ver < kRoomVersion_250a)) {
 		return new RoomFileError(kRoomFileErr_IncompatibleEngine, "Pre-2.5 graphical scripts are no longer supported.");
 		/* NOTE: implementation hidden in room_file_deprecated.cpp
-		    ReadPre250Scripts(in);
+			ReadPre250Scripts(in);
 		*/
 	}
 
@@ -348,7 +348,7 @@ HRoomFileError ReadObjNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion d
 	size_t name_count = in->ReadByte();
 	if (name_count != room->ObjectCount)
 		return new RoomFileError(kRoomFileErr_InconsistentData,
-		                         String::FromFormat("In the object names block, expected name count: %d, got %d", room->ObjectCount, name_count));
+			String::FromFormat("In the object names block, expected name count: %d, got %d", room->ObjectCount, name_count));
 
 	for (size_t i = 0; i < room->ObjectCount; ++i) {
 		if (data_ver >= kRoomVersion_3415)
@@ -364,7 +364,7 @@ HRoomFileError ReadObjScNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion
 	size_t name_count = in->ReadByte();
 	if (name_count != room->ObjectCount)
 		return new RoomFileError(kRoomFileErr_InconsistentData,
-		                         String::FromFormat("In the object script names block, expected name count: %d, got %d", room->ObjectCount, name_count));
+			String::FromFormat("In the object script names block, expected name count: %d, got %d", room->ObjectCount, name_count));
 
 	for (size_t i = 0; i < room->ObjectCount; ++i) {
 		if (data_ver >= kRoomVersion_3415)
@@ -415,7 +415,7 @@ HRoomFileError ReadPropertiesBlock(RoomStruct *room, Stream *in, RoomFileVersion
 }
 
 HRoomFileError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block, const String &ext_id,
-                             soff_t block_len, RoomFileVersion data_ver) {
+	soff_t block_len, RoomFileVersion data_ver) {
 	//
 	// First check classic block types, identified with a numeric id
 	//
@@ -438,12 +438,12 @@ HRoomFileError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block,
 	case kRoomFblk_CompScript:
 	case kRoomFblk_CompScript2:
 		return new RoomFileError(kRoomFileErr_OldBlockNotSupported,
-		                         String::FromFormat("Type: %d.", block));
+			String::FromFormat("Type: %d.", block));
 	case kRoomFblk_None:
 		break; // continue to string ids
 	default:
 		return new RoomFileError(kRoomFileErr_UnknownBlockType,
-		                         String::FromFormat("Type: %d, known range: %d - %d.", block, kRoomFblk_Main, kRoomFblk_ObjectScNames));
+			String::FromFormat("Type: %d, known range: %d - %d.", block, kRoomFblk_Main, kRoomFblk_ObjectScNames));
 	}
 
 	// Add extensions here checking ext_id, which is an up to 16-chars name, for example:
@@ -452,44 +452,23 @@ HRoomFileError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block,
 	//     // read new region properties
 	// }
 	return new RoomFileError(kRoomFileErr_UnknownBlockType,
-	                         String::FromFormat("Type: %s", ext_id.GetCStr()));
+		String::FromFormat("Type: %s", ext_id.GetCStr()));
+}
+
+// This reader will process all blocks inside ReadRoomBlock() function,
+// and read compatible data into the given RoomStruct
+static RoomStruct *reader_room;
+
+static HRoomFileError ReadRoomDataReader(Stream *in,
+		RoomFileBlock block_id, const String &ext_id,
+		soff_t block_len, RoomFileVersion data_ver, bool &read_next) {
+	return ReadRoomBlock(reader_room, in, block_id, ext_id, block_len, data_ver);
 }
 
 HRoomFileError ReadRoomData(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	room->DataVersion = data_ver;
-
-	// Read list of data blocks. The block meta format is shared with the main game file extensions now.
-	//    - 1 byte - old format block ID, 0xFF indicates end of list.
-	//    - 16 bytes - new string ID of an extension. \0 at the first byte indicates end of list.
-	//    - 4 or 8 bytes - length of extension data, in bytes (depends on format version).
-	while (true) {
-		update_polled_stuff_if_runtime();
-		RoomFileBlock block_id;
-		String ext_id;
-		soff_t block_len;
-		HRoomFileError err = OpenNextRoomBlock(in, data_ver, block_id, ext_id, block_len);
-		if (!err)
-			return err;
-		if (ext_id.IsEmpty())
-			break; // end of list
-
-		soff_t block_end = in->GetPosition() + block_len;
-		err = ReadRoomBlock(room, in, block_id, ext_id, block_len, data_ver);
-		if (!err)
-			return err;
-
-		soff_t cur_pos = in->GetPosition();
-		if (cur_pos > block_end) {
-			return new RoomFileError(kRoomFileErr_BlockDataOverlapping,
-			                         String::FromFormat("Block: %s, expected to end at offset: %u, finished reading at %u.",
-			                                 ext_id.GetCStr(), block_end, cur_pos));
-		} else if (cur_pos < block_end) {
-			Debug::Printf(kDbgMsg_Warn, "WARNING: room data blocks nonsequential, block type %s expected to end at %lld, finished reading at %lld",
-			              ext_id.GetCStr(), block_end, cur_pos);
-			in->Seek(block_end, Shared::kSeekBegin);
-		}
-	}
-	return HRoomFileError::None();
+	reader_room = room;
+	return ReadRoomData(ReadRoomDataReader, in, data_ver);
 }
 
 HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos) {
@@ -621,31 +600,33 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g
 	return HRoomFileError::None();
 }
 
-HRoomFileError ExtractScriptText(String &script, Stream *in, RoomFileVersion data_ver) {
-	HRoomFileError err;
-
-	while (true) {
-		RoomFileBlock block_id;
-		String ext_id;
-		soff_t block_len;
-		err = OpenNextRoomBlock(in, data_ver, block_id, ext_id, block_len);
-		if (!err)
-			return err;
-		if (ext_id.IsEmpty())
-			break; // end of list
-
-		if (block_id == kRoomFblk_Script) {
-			char *buf = nullptr;
-			err = ReadScriptBlock(buf, in, data_ver);
-			if (err) {
-				script = buf;
-				delete buf;
-			}
-			return err;
+// Reader for ExtractScripText
+static String *reader_script;
+
+HRoomFileError ExtractScriptTextReader(Stream *in,
+		RoomFileBlock block_id, const String &ext_id, soff_t block_len,
+		RoomFileVersion data_ver, bool &read_next) {
+	if (block_id == kRoomFblk_Script) {
+		read_next = false;
+		char *buf = nullptr;
+		HRoomFileError err = ReadScriptBlock(buf, in, data_ver);
+		if (err) {
+			*reader_script = buf;
+			delete buf;
 		}
-		in->Seek(block_len); // skip block
-	};
-	return new RoomFileError(kRoomFileErr_BlockNotFound);
+		return err;
+	}
+	in->Seek(block_len); // skip block
+	return HRoomFileError::None();
+}
+
+HRoomFileError ExtractScriptText(String &script, Stream *in, RoomFileVersion data_ver) {
+	// This reader would only process kRoomFblk_Script and exit as soon as one is found
+	reader_script = &script;
+	HRoomFileError err = ReadRoomData(ExtractScriptTextReader, in, data_ver);
+	if (err && script.IsEmpty())
+		new RoomFileError(kRoomFileErr_BlockNotFound);
+	return err;
 }
 
 void WriteInteractionScripts(const InteractionScripts *interactions, Stream *out) {
diff --git a/engines/ags/shared/game/room_file.h b/engines/ags/shared/game/room_file.h
index b9ce7d601c..7d6306900f 100644
--- a/engines/ags/shared/game/room_file.h
+++ b/engines/ags/shared/game/room_file.h
@@ -130,6 +130,11 @@ HRoomFileError WriteRoomData(const RoomStruct *room, Stream *out, RoomFileVersio
 HRoomFileError ReadRoomHeader(RoomDataSource &src);
 // Opens next room block from the stream, fills in its identifier and length on success
 HRoomFileError OpenNextRoomBlock(Stream *in, RoomFileVersion data_ver, RoomFileBlock &block_id, String &ext_id, soff_t &block_len);
+// Type of function that reads single room block and tells whether to continue reading
+typedef HRoomFileError(*PfnReadRoomBlock)(Stream * in, RoomFileBlock block_id, const String & ext_id,
+	soff_t block_len, RoomFileVersion data_ver, bool &read_next);
+// Parses room file, passing each found block into callback; does not read any actual data itself
+HRoomFileError ReadRoomData(PfnReadRoomBlock reader, Stream *in, RoomFileVersion data_ver);
 // Type of function that writes single room block.
 typedef void(*PfnWriteRoomBlock)(const RoomStruct *room, Stream *out);
 // Writes room block with a new-style string id
diff --git a/engines/ags/shared/game/room_file_base.cpp b/engines/ags/shared/game/room_file_base.cpp
index f934131829..51ab28cb3f 100644
--- a/engines/ags/shared/game/room_file_base.cpp
+++ b/engines/ags/shared/game/room_file_base.cpp
@@ -22,6 +22,7 @@
 
 #include "ags/shared/game/room_file.h"
 #include "ags/shared/util/file.h"
+#include "ags/shared/debugging/out.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -124,6 +125,44 @@ HRoomFileError OpenNextRoomBlock(Stream *in, RoomFileVersion data_ver, RoomFileB
 	return HRoomFileError::None();
 }
 
+HRoomFileError ReadRoomData(PfnReadRoomBlock reader, Stream *in, RoomFileVersion data_ver) {
+	// Read list of data blocks. The block meta format is shared with the main game file extensions now.
+	//    - 1 byte - old format block ID, 0xFF indicates end of list.
+	//    - 16 bytes - new string ID of an extension. \0 at the first byte indicates end of list.
+	//    - 4 or 8 bytes - length of extension data, in bytes (depends on format version).
+	while (true) {
+		RoomFileBlock block_id;
+		String ext_id;
+		soff_t block_len;
+		HRoomFileError err = OpenNextRoomBlock(in, data_ver, block_id, ext_id, block_len);
+		if (!err)
+			return err;
+		if (ext_id.IsEmpty())
+			break; // end of list
+
+		soff_t block_end = in->GetPosition() + block_len;
+		bool read_next = true;
+		err = reader(in, block_id, ext_id, block_len, data_ver, read_next);
+		if (!err)
+			return err;
+
+		soff_t cur_pos = in->GetPosition();
+		if (cur_pos > block_end) {
+			return new RoomFileError(kRoomFileErr_BlockDataOverlapping,
+				String::FromFormat("Block: %s, expected to end at offset: %u, finished reading at %u.",
+					ext_id.GetCStr(), block_end, cur_pos));
+		} else if (cur_pos < block_end) {
+			Debug::Printf(kDbgMsg_Warn, "WARNING: room data blocks nonsequential, block type %s expected to end at %u, finished reading at %u",
+				ext_id.GetCStr(), block_end, cur_pos);
+			in->Seek(block_end, Shared::kSeekBegin);
+		}
+
+		if (!read_next)
+			break;
+	}
+	return HRoomFileError::None();
+}
+
 // Generic function that saves a block and automatically adds its size into header
 static void WriteRoomBlock(const RoomStruct *room, RoomFileBlock block, const String &ext_id, PfnWriteRoomBlock writer, Stream *out) {
 	// Write block's header


Commit: fdca14a38d9cd13ef7ff240fe9bae1e7e28f5151
    https://github.com/scummvm/scummvm/commit/fdca14a38d9cd13ef7ff240fe9bae1e7e28f5151
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:11-07:00

Commit Message:
AGS: Replaced TreeMap with std::unordered_map for translations

>From upstream 3a4603dccc175736dfc20daf3376819dfb2060e8

Changed paths:
  R engines/ags/engine/ac/tree_map.cpp
  R engines/ags/engine/ac/tree_map.h
    engines/ags/engine/ac/global_debug.cpp
    engines/ags/engine/ac/global_translation.cpp
    engines/ags/engine/ac/translation.cpp
    engines/ags/engine/ac/translation.h
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/module.mk


diff --git a/engines/ags/engine/ac/global_debug.cpp b/engines/ags/engine/ac/global_debug.cpp
index 71b4c9197c..3e7e71868b 100644
--- a/engines/ags/engine/ac/global_debug.cpp
+++ b/engines/ags/engine/ac/global_debug.cpp
@@ -35,7 +35,6 @@
 #include "ags/engine/ac/properties.h"
 #include "ags/engine/ac/sys_events.h"
 #include "ags/engine/ac/translation.h"
-#include "ags/engine/ac/tree_map.h"
 #include "ags/engine/ac/walkable_area.h"
 #include "ags/engine/gfx/gfxfilter.h"
 #include "ags/engine/gui/gui_dialog.h"
@@ -72,7 +71,7 @@ String GetRuntimeInfo() {
 		runtimeInfo.Append("[AUDIO.VOX enabled");
 	if (_GP(play).want_speech >= 1)
 		runtimeInfo.Append("[SPEECH.VOX enabled");
-	if (get_translation_tree() != nullptr) {
+	if (get_translation_tree().size() > 0) {
 		runtimeInfo.Append("[Using translation ");
 		runtimeInfo.Append(get_translation_name());
 	}
diff --git a/engines/ags/engine/ac/global_translation.cpp b/engines/ags/engine/ac/global_translation.cpp
index d9091765d6..56e1bcef24 100644
--- a/engines/ags/engine/ac/global_translation.cpp
+++ b/engines/ags/engine/ac/global_translation.cpp
@@ -26,7 +26,6 @@
 #include "ags/engine/ac/global_translation.h"
 #include "ags/engine/ac/string.h"
 #include "ags/engine/ac/translation.h"
-#include "ags/engine/ac/tree_map.h"
 #include "ags/engine/platform/base/ags_platform_driver.h"
 #include "ags/plugins/ags_plugin.h"
 #include "ags/plugins/plugin_engine.h"
@@ -53,19 +52,17 @@ const char *get_translation(const char *text) {
 	}
 #endif
 
-	const auto *transtree = get_translation_tree();
-	if (transtree != nullptr) {
-		// translate the text using the translation file
-		const char *transl = transtree->findValue(text);
-		if (transl != nullptr)
-			return transl;
-	}
+	const auto &transtree = get_translation_tree();
+	const auto it = transtree.find(text);
+	if (it != transtree.end())
+		return it->_value.GetCStr();
+
 	// return the original text
 	return text;
 }
 
 int IsTranslationAvailable() {
-	if (get_translation_tree() != nullptr)
+	if (get_translation_tree().size() > 0)
 		return 1;
 	return 0;
 }
diff --git a/engines/ags/engine/ac/translation.cpp b/engines/ags/engine/ac/translation.cpp
index 32de40893b..55210aaf0d 100644
--- a/engines/ags/engine/ac/translation.cpp
+++ b/engines/ags/engine/ac/translation.cpp
@@ -29,7 +29,6 @@
 #include "ags/engine/ac/global_game.h"
 #include "ags/engine/ac/runtime_defines.h"
 #include "ags/engine/ac/translation.h"
-#include "ags/engine/ac/tree_map.h"
 #include "ags/shared/ac/words_dictionary.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/shared/util/misc.h"
@@ -42,8 +41,7 @@ namespace AGS3 {
 using namespace AGS::Shared;
 
 void close_translation() {
-	delete _G(transtree);
-	_G(transtree) = nullptr;
+	_GP(transtree).clear();
 	_G(trans_name) = "";
 	_G(trans_filename) = "";
 }
@@ -70,8 +68,7 @@ bool init_translation(const String &lang, const String &fallback_lang, bool quit
 		return false;
 	}
 
-	delete _G(transtree);
-	_G(transtree) = new TreeMap();
+	_GP(transtree).clear();
 
 	String parse_error;
 	bool result = parse_translation(language_file, parse_error);
@@ -104,8 +101,8 @@ String get_translation_path() {
 	return _G(trans_filename);
 }
 
-const TreeMap *get_translation_tree() {
-	return _G(transtree);
+const StringMap &get_translation_tree() {
+	return _GP(transtree);
 }
 
 bool parse_translation(Stream *language_file, String &parse_error) {
@@ -127,7 +124,7 @@ bool parse_translation(Stream *language_file, String &parse_error) {
 					parse_error = "Translation file is corrupt";
 					return false;
 				}
-				_G(transtree)->addText(original, translation);
+				_GP(transtree).insert(std::make_pair(String(original), String(translation)));
 			}
 
 		} else if (blockType == 2) {
@@ -165,7 +162,7 @@ bool parse_translation(Stream *language_file, String &parse_error) {
 		}
 	}
 
-	if (_G(transtree)->text == nullptr) {
+	if (_GP(transtree).size() == 0) {
 		parse_error = "The translation file was empty.";
 		return false;
 	}
diff --git a/engines/ags/engine/ac/translation.h b/engines/ags/engine/ac/translation.h
index 4a1348a9d3..78d115f5f7 100644
--- a/engines/ags/engine/ac/translation.h
+++ b/engines/ags/engine/ac/translation.h
@@ -24,11 +24,12 @@
 #define AGS_ENGINE_AC_TRANSLATION_H
 
 #include "ags/shared/util/string.h"
+#include "ags/shared/util/string_types.h"
 
 namespace AGS3 {
 
 using AGS::Shared::String;
-struct TreeMap;
+using AGS::Shared::StringMap;
 
 void close_translation();
 bool init_translation(const String &lang, const String &fallback_lang, bool quit_on_error);
@@ -37,7 +38,7 @@ String get_translation_name();
 // Returns fill path to the translation file, or empty string if default translation is used
 String get_translation_path();
 // Returns translation map for reading only
-const TreeMap *get_translation_tree();
+const StringMap &get_translation_tree();
 
 } // namespace AGS3
 
diff --git a/engines/ags/engine/ac/tree_map.cpp b/engines/ags/engine/ac/tree_map.cpp
deleted file mode 100644
index fc41e2e8ab..0000000000
--- a/engines/ags/engine/ac/tree_map.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/str.h"
-#include "ags/shared/ac/common.h"
-#include "ags/engine/ac/tree_map.h"
-
-namespace AGS3 {
-
-TreeMap::TreeMap() {
-	left = nullptr;
-	right = nullptr;
-	text = nullptr;
-	translation = nullptr;
-}
-
-const char *TreeMap::findValue(const char *key) const {
-	if (text == nullptr)
-		return nullptr;
-
-	if (strcmp(key, text) == 0)
-		return translation;
-
-	if (strcmp(key, text) < 0) {
-		if (left == nullptr)
-			return nullptr;
-		return left->findValue(key);
-	} else {
-		if (right == nullptr)
-			return nullptr;
-		return right->findValue(key);
-	}
-}
-
-void TreeMap::addText(const char *ntx, char *trans) {
-	if ((ntx == nullptr) || (ntx[0] == 0) ||
-	        ((text != nullptr) && (strcmp(ntx, text) == 0)))
-		// don't add if it's an empty string or if it's already here
-		return;
-
-	if (text == nullptr) {
-		text = (char *)malloc(strlen(ntx) + 1);
-		translation = (char *)malloc(strlen(trans) + 1);
-		if (translation == nullptr)
-			quit("load_translation: out of memory");
-		strcpy(text, ntx);
-		strcpy(translation, trans);
-	} else if (strcmp(ntx, text) < 0) {
-		// Earlier in alphabet, add to left
-		if (left == nullptr)
-			left = new TreeMap();
-
-		left->addText(ntx, trans);
-	} else if (strcmp(ntx, text) > 0) {
-		// Later in alphabet, add to right
-		if (right == nullptr)
-			right = new TreeMap();
-
-		right->addText(ntx, trans);
-	}
-}
-
-void TreeMap::clear() {
-	if (left) {
-		left->clear();
-		delete left;
-	}
-	if (right) {
-		right->clear();
-		delete right;
-	}
-	if (text)
-		free(text);
-	if (translation)
-		free(translation);
-	left = nullptr;
-	right = nullptr;
-	text = nullptr;
-	translation = nullptr;
-}
-
-TreeMap::~TreeMap() {
-	clear();
-}
-
-} // namespace AGS3
diff --git a/engines/ags/engine/ac/tree_map.h b/engines/ags/engine/ac/tree_map.h
deleted file mode 100644
index c19ff428ec..0000000000
--- a/engines/ags/engine/ac/tree_map.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-//=============================================================================
-//
-// TODO: remove and replace with std::map / unordered_map?
-// some helper functions may be required too.
-//=============================================================================
-
-#ifndef AGS_ENGINE_AC_TREE_MAP_H
-#define AGS_ENGINE_AC_TREE_MAP_H
-
-namespace AGS3 {
-
-// Binary tree structure for holding translations, allows fast
-// access
-struct TreeMap {
-	TreeMap *left, *right;
-	char *text;
-	char *translation;
-
-	TreeMap();
-	const char *findValue(const char *key) const;
-	void addText(const char *ntx, char *trans);
-	void clear();
-	~TreeMap();
-};
-
-} // namespace AGS3
-
-#endif
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 2e44efb072..a4e47af522 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -332,6 +332,9 @@ Globals::Globals() {
 	_simp = new SystemImports();
 	_simp_for_plugin = new SystemImports();
 
+	// translation.cpp globals
+	_transtree = new StringMap();
+
 	// walk_behind.cpp globals
 	Common::fill(_walkBehindLeft, _walkBehindLeft + MAX_WALK_BEHINDS, 0);
 	Common::fill(_walkBehindTop, _walkBehindTop + MAX_WALK_BEHINDS, 0);
@@ -543,6 +546,9 @@ Globals::~Globals() {
 	// system_imports.cpp globals
 	delete _simp;
 	delete _simp_for_plugin;
+
+	// translation.cpp globals
+	delete _transtree;
 }
 
 } // namespace AGS3
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index bc27fc8dba..491a444c37 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -25,6 +25,7 @@
 
 #include "ags/shared/ac/game_version.h"
 #include "ags/shared/util/string.h"
+#include "ags/shared/util/string_types.h"
 #include "ags/shared/util/version.h"
 #include "ags/shared/gui/gui_main.h"
 #include "ags/shared/script/cc_script.h"
@@ -53,6 +54,7 @@ namespace AGS3 {
 
 using String = AGS::Shared::String;
 using Version = AGS::Shared::Version;
+using StringMap = AGS::Shared::StringMap;
 
 namespace AGS {
 namespace Shared {
@@ -162,7 +164,6 @@ struct StaticArray;
 struct StaticGame;
 struct SystemImports;
 struct TopBarSettings;
-struct TreeMap;
 struct ViewStruct;
 
 class Globals {
@@ -1310,7 +1311,7 @@ public:
 	 * @{
 	 */
 
-	TreeMap *_transtree = nullptr;
+	StringMap *_transtree = nullptr;
 	String _trans_name, _trans_filename;
 	long _lang_offs_start = 0;
 	char _transFileName[MAX_PATH] = { 0 };
diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index 2cff913501..18c6a32aeb 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -191,7 +191,6 @@ MODULE_OBJS = \
 	engine/ac/textbox.o \
 	engine/ac/timer.o \
 	engine/ac/translation.o \
-	engine/ac/tree_map.o \
 	engine/ac/view_frame.o \
 	engine/ac/viewport_script.o \
 	engine/ac/walkable_area.o \


Commit: f9130677502d38b65247f20ac13e26d418349f92
    https://github.com/scummvm/scummvm/commit/f9130677502d38b65247f20ac13e26d418349f92
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:11-07:00

Commit Message:
AGS: Reimplemented Translation reading in Common, similar to Game and Room

>From upstream cae33966338b24a0d2527bc0c537ac65fe39eddb

Changed paths:
  A engines/ags/shared/game/tra_file.cpp
  A engines/ags/shared/game/tra_file.h
    engines/ags/engine/ac/translation.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/module.mk


diff --git a/engines/ags/engine/ac/translation.cpp b/engines/ags/engine/ac/translation.cpp
index 55210aaf0d..3d839e8905 100644
--- a/engines/ags/engine/ac/translation.cpp
+++ b/engines/ags/engine/ac/translation.cpp
@@ -20,7 +20,6 @@
  *
  */
 
-//include <cstdio>
 #include "ags/engine/ac/asset_helper.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/game_setup.h"
@@ -31,6 +30,7 @@
 #include "ags/engine/ac/translation.h"
 #include "ags/shared/ac/words_dictionary.h"
 #include "ags/shared/debugging/out.h"
+#include "ags/shared/game/tra_file.h"
 #include "ags/shared/util/misc.h"
 #include "ags/shared/util/stream.h"
 #include "ags/shared/core/asset_manager.h"
@@ -42,46 +42,43 @@ using namespace AGS::Shared;
 
 void close_translation() {
 	_GP(transtree).clear();
+	_GP(trans) = Translation();
 	_G(trans_name) = "";
 	_G(trans_filename) = "";
 }
 
-bool parse_translation(Stream *language_file, String &parse_error);
-
 bool init_translation(const String &lang, const String &fallback_lang, bool quit_on_error) {
 
 	if (lang.IsEmpty())
 		return false;
 	_G(trans_filename) = String::FromFormat("%s.tra", lang.GetCStr());
 
-	Stream *language_file = _GP(AssetMgr)->OpenAsset(_G(trans_filename));
-	if (language_file == nullptr) {
+	std::unique_ptr<Stream> in(_GP(AssetMgr)->OpenAsset(_G(trans_filename)));
+	if (in == nullptr) {
 		Debug::Printf(kDbgMsg_Error, "Cannot open translation: %s", _G(trans_filename).GetCStr());
 		return false;
 	}
 
-	char transsig[16] = { 0 };
-	language_file->Read(transsig, 15);
-	if (strcmp(transsig, "AGSTranslation") != 0) {
-		Debug::Printf(kDbgMsg_Error, "Translation signature mismatch: %s", _G(trans_filename).GetCStr());
-		delete language_file;
-		return false;
-	}
-
-	_GP(transtree).clear();
+	_GP(trans) = Translation();
 
-	String parse_error;
-	bool result = parse_translation(language_file, parse_error);
-	delete language_file;
+	// First test if the translation is meant for this game
+	HTraFileError err = TestTraGameID(_GP(game).uniqueid, _GP(game).gamename, in.get());
+	if (err) {
+		// If successful, then read translation data fully
+		in.reset(_GP(AssetMgr)->OpenAsset(_G(trans_filename)));
+		err = ReadTraData(_GP(trans), in.get());
+	}
 
-	if (!result) {
-		parse_error.Prepend(String::FromFormat("Failed to read translation file: %s:\n", _G(trans_filename).GetCStr()));
+	// Process errors
+	if (!err) {
+		String err_msg = String::FromFormat("Failed to read translation file: %s:\n%s",
+			_G(trans_filename).GetCStr(),
+			err->FullMessage().GetCStr());
 		close_translation();
 		if (quit_on_error) {
-			parse_error.PrependChar('!');
-			quit(parse_error);
+			quitprintf("!%s", err_msg.GetCStr());
 		} else {
-			Debug::Printf(kDbgMsg_Error, parse_error);
+			Debug::Printf(kDbgMsg_Error, err_msg);
 			if (!fallback_lang.IsEmpty()) {
 				Debug::Printf("Fallback to translation: %s", fallback_lang.GetCStr());
 				init_translation(fallback_lang, "", false);
@@ -89,6 +86,21 @@ bool init_translation(const String &lang, const String &fallback_lang, bool quit
 			return false;
 		}
 	}
+
+	// Translation read successfully
+	// Configure new game settings
+	if (_GP(trans).NormalFont >= 0)
+		SetNormalFont(_GP(trans).NormalFont);
+	if (_GP(trans).SpeechFont >= 0)
+		SetSpeechFont(_GP(trans).SpeechFont);
+	if (_GP(trans).RightToLeft == 1) {
+		_GP(play).text_align = kHAlignLeft;
+		_GP(game).options[OPT_RIGHTLEFTWRITE] = 0;
+	} else if (_GP(trans).RightToLeft == 2) {
+		_GP(play).text_align = kHAlignRight;
+		_GP(game).options[OPT_RIGHTLEFTWRITE] = 1;
+	}
+
 	Debug::Printf("Translation initialized: %s", _G(trans_filename).GetCStr());
 	return true;
 }
@@ -102,72 +114,7 @@ String get_translation_path() {
 }
 
 const StringMap &get_translation_tree() {
-	return _GP(transtree);
-}
-
-bool parse_translation(Stream *language_file, String &parse_error) {
-	while (!language_file->EOS()) {
-		int blockType = language_file->ReadInt32();
-		if (blockType == -1)
-			break;
-		// MACPORT FIX 9/6/5: remove warning
-		/* int blockSize = */ language_file->ReadInt32();
-
-		if (blockType == 1) {
-			char original[STD_BUFFER_SIZE], translation[STD_BUFFER_SIZE];
-			while (1) {
-				read_string_decrypt(language_file, original, STD_BUFFER_SIZE);
-				read_string_decrypt(language_file, translation, STD_BUFFER_SIZE);
-				if ((strlen(original) < 1) && (strlen(translation) < 1))
-					break;
-				if (language_file->EOS()) {
-					parse_error = "Translation file is corrupt";
-					return false;
-				}
-				_GP(transtree).insert(std::make_pair(String(original), String(translation)));
-			}
-
-		} else if (blockType == 2) {
-			int uidfrom;
-			char wasgamename[100];
-			uidfrom = language_file->ReadInt32();
-			read_string_decrypt(language_file, wasgamename, sizeof(wasgamename));
-			if ((uidfrom != _GP(game).uniqueid) || (strcmp(wasgamename, _GP(game).gamename) != 0)) {
-				parse_error.Format("The translation file is not compatible with this _GP(game). The translation is designed for '%s'.",
-				                   wasgamename);
-				return false;
-			}
-		} else if (blockType == 3) {
-			// game settings
-			int temp = language_file->ReadInt32();
-			// normal font
-			if (temp >= 0)
-				SetNormalFont(temp);
-			temp = language_file->ReadInt32();
-			// speech font
-			if (temp >= 0)
-				SetSpeechFont(temp);
-			temp = language_file->ReadInt32();
-			// text direction
-			if (temp == 1) {
-				_GP(play).text_align = kHAlignLeft;
-				_GP(game).options[OPT_RIGHTLEFTWRITE] = 0;
-			} else if (temp == 2) {
-				_GP(play).text_align = kHAlignRight;
-				_GP(game).options[OPT_RIGHTLEFTWRITE] = 1;
-			}
-		} else {
-			parse_error.Format("Unknown block type in translation file (%d).", blockType);
-			return false;
-		}
-	}
-
-	if (_GP(transtree).size() == 0) {
-		parse_error = "The translation file was empty.";
-		return false;
-	}
-
-	return true;
+	return _GP(trans).Dict;
 }
 
 } // namespace AGS3
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index a4e47af522..a84082fb10 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -30,6 +30,7 @@
 #include "ags/shared/font/wfn_font_renderer.h"
 #include "ags/shared/game/interactions.h"
 #include "ags/shared/game/room_struct.h"
+#include "ags/shared/game/tra_file.h"
 #include "ags/shared/gui/gui_button.h"
 #include "ags/shared/gui/gui_inv.h"
 #include "ags/shared/gui/gui_label.h"
@@ -333,6 +334,7 @@ Globals::Globals() {
 	_simp_for_plugin = new SystemImports();
 
 	// translation.cpp globals
+	_trans = new AGS::Shared::Translation();
 	_transtree = new StringMap();
 
 	// walk_behind.cpp globals
@@ -548,6 +550,7 @@ Globals::~Globals() {
 	delete _simp_for_plugin;
 
 	// translation.cpp globals
+	delete _trans;
 	delete _transtree;
 }
 
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 491a444c37..c493d51ca8 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -72,6 +72,7 @@ class GUITextBox;
 struct InteractionVariable;
 struct PlaneScaling;
 class RoomStruct;
+struct Translation;
 
 } // namespace Shared
 
@@ -1311,6 +1312,7 @@ public:
 	 * @{
 	 */
 
+	AGS::Shared::Translation *_trans;
 	StringMap *_transtree = nullptr;
 	String _trans_name, _trans_filename;
 	long _lang_offs_start = 0;
diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index 18c6a32aeb..c7168ca467 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -56,6 +56,7 @@ MODULE_OBJS = \
 	shared/game/room_file_base.o \
 	shared/game/room_file_deprecated.o \
 	shared/game/room_struct.o \
+	shared/game/tra_file.o \
 	shared/gfx/allegro_bitmap.o \
 	shared/gfx/bitmap.o \
 	shared/gfx/image.o \
diff --git a/engines/ags/shared/game/tra_file.cpp b/engines/ags/shared/game/tra_file.cpp
new file mode 100644
index 0000000000..7237f530b0
--- /dev/null
+++ b/engines/ags/shared/game/tra_file.cpp
@@ -0,0 +1,177 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/shared/game/tra_file.h"
+#include "ags/shared/ac/words_dictionary.h"
+#include "ags/shared/debugging/out.h"
+#include "ags/shared/util/string_compat.h"
+
+namespace AGS3 {
+namespace AGS {
+namespace Shared {
+
+String GetTraFileErrorText(TraFileErrorType err) {
+	switch (err) {
+	case kTraFileErr_NoError:
+		return "No error.";
+	case kTraFileErr_SignatureFailed:
+		return "Not an AGS translation file or an unsupported format.";
+	case kTraFileErr_FormatNotSupported:
+		return "Format version not supported.";
+	case kTraFileErr_GameIDMismatch:
+		return "Game ID does not match, translation is meant for a different game.";
+	case kTraFileErr_UnexpectedEOF:
+		return "Unexpected end of file.";
+	case kTraFileErr_UnknownBlockType:
+		return "Unknown block type.";
+	case kTraFileErr_BlockDataOverlapping:
+		return "Block data overlapping.";
+	}
+	return "Unknown error.";
+}
+
+String GetTraBlockName(TraFileBlock id) {
+	switch (id) {
+	case kTraFblk_Dict: return "Dictionary";
+	case kTraFblk_GameID: return "GameID";
+	case kTraFblk_TextOpts: return "TextOpts";
+	}
+	return "unknown";
+}
+
+HTraFileError ReadTraBlock(Translation &tra, Stream *in, TraFileBlock block, soff_t block_len) {
+	switch (block) {
+	case kTraFblk_Dict: {
+		char original[1024];
+		char translation[1024];
+		// Read lines until we find zero-length key & value
+		while (true) {
+			read_string_decrypt(in, original, 1024);
+			read_string_decrypt(in, translation, 1024);
+			if (!original[0] && !translation[0])
+				break;
+			tra.Dict.insert(std::make_pair(String(original), String(translation)));
+		}
+	}
+	break;
+	case kTraFblk_GameID: {
+		char gamename[256];
+		tra.GameUid = in->ReadInt32();
+		read_string_decrypt(in, gamename, 256);
+		tra.GameName = gamename;
+	}
+	break;
+	case kTraFblk_TextOpts:
+		tra.NormalFont = in->ReadInt32();
+		tra.SpeechFont = in->ReadInt32();
+		tra.RightToLeft = in->ReadInt32();
+		break;
+	default:
+		return new TraFileError(kTraFileErr_UnknownBlockType,
+			String::FromFormat("Type: %d, known range: %d - %d.", block, kTraFblk_Dict, kTraFblk_TextOpts));
+	}
+	return HTraFileError::None();
+}
+
+HTraFileError ReadTraData(PfnReadTraBlock reader, Stream *in) {
+	// Test the file signature
+	const char *tra_sig = "AGSTranslation";
+	char sigbuf[16] = { 0 };
+	in->Read(sigbuf, 15);
+	if (ags_stricmp(tra_sig, sigbuf) != 0)
+		return new TraFileError(kTraFileErr_SignatureFailed);
+
+	while (!in->EOS()) {
+		TraFileBlock block_id = (TraFileBlock)in->ReadInt32();
+		if (block_id == kTraFile_EOF)
+			break; // end of list
+
+		soff_t block_len = in->ReadInt32();
+		soff_t block_end = in->GetPosition() + block_len;
+		String ext_id = GetTraBlockName(block_id);
+
+		bool read_next = true;
+		HTraFileError err = reader(in, block_id, block_len, read_next);
+		if (!err)
+			return err;
+
+		soff_t cur_pos = in->GetPosition();
+		if (cur_pos > block_end) {
+			return new TraFileError(kTraFileErr_BlockDataOverlapping,
+				String::FromFormat("Block: %s, expected to end at offset: %lld, finished reading at %lld.",
+					ext_id.GetCStr(), block_end, cur_pos));
+		} else if (cur_pos < block_end) {
+			Debug::Printf(kDbgMsg_Warn,
+				"WARNING: translation data blocks nonsequential, block type %s expected to end at %lld, finished reading at %lld",
+				ext_id.GetCStr(), block_end, cur_pos);
+			in->Seek(block_end, Shared::kSeekBegin);
+		}
+
+		if (!read_next)
+			break;
+	}
+	return HTraFileError::None();
+}
+
+static Translation *reader_tra;
+
+HTraFileError TestTraGameIDReader(Stream *in, TraFileBlock block_id,
+		soff_t block_len, bool &read_next) {
+	if (block_id == kTraFblk_GameID) {
+		read_next = false;
+		return ReadTraBlock(*reader_tra, in, block_id, block_len);
+	}
+	in->Seek(block_len); // skip block
+	return HTraFileError::None();
+}
+
+HTraFileError TestTraGameID(int game_uid, const String &game_name, Stream *in) {
+	// This reader would only process kTraFblk_GameID and exit as soon as one is found
+	Translation tra;
+	reader_tra = &tra;
+
+	HTraFileError err = ReadTraData(TestTraGameIDReader, in);
+	if (!err)
+		return err;
+	// Test the identifiers, if they are not present then skip the test
+	if ((tra.GameUid != 0 && (game_uid != tra.GameUid)) ||
+		!tra.GameName.IsEmpty() && (game_name != tra.GameName))
+		return new TraFileError(kTraFileErr_GameIDMismatch,
+			String::FromFormat("The translation is designed for '%s'", tra.GameName.GetCStr()));
+	return HTraFileError::None();
+}
+
+HTraFileError ReadTraDataReader(Stream *in, TraFileBlock block_id,
+		soff_t block_len, bool &read_next) {
+	return ReadTraBlock(*reader_tra, in, block_id, block_len);
+}
+
+HTraFileError ReadTraData(Translation &tra, Stream *in) {
+	// This reader will process all blocks inside ReadTraBlock() function,
+	// and read compatible data into the given Translation object
+	reader_tra = &tra;
+	return ReadTraData(ReadTraDataReader, in);
+}
+
+} // namespace Shared
+} // namespace AGS
+} // namespace AGS3
diff --git a/engines/ags/shared/game/tra_file.h b/engines/ags/shared/game/tra_file.h
new file mode 100644
index 0000000000..4e630b8962
--- /dev/null
+++ b/engines/ags/shared/game/tra_file.h
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+ //=============================================================================
+ //
+ // This unit provides functions for reading compiled translation file.
+ //
+ //=============================================================================
+
+#ifndef AGS_SHARED_GAME_TRA_FILE_H
+#define AGS_SHARED_GAME_TRA_FILE_H
+
+#include "ags/shared/util/error.h"
+#include "ags/shared/util/stream.h"
+#include "ags/shared/util/string_types.h"
+
+namespace AGS3 {
+namespace AGS {
+namespace Shared {
+
+enum TraFileErrorType {
+	kTraFileErr_NoError,
+	kTraFileErr_SignatureFailed,
+	kTraFileErr_FormatNotSupported,
+	kTraFileErr_GameIDMismatch,
+	kTraFileErr_UnexpectedEOF,
+	kTraFileErr_UnknownBlockType,
+	kTraFileErr_BlockDataOverlapping,
+};
+
+enum TraFileBlock {
+	kTraFblk_Dict = 1,
+	kTraFblk_GameID = 2,
+	kTraFblk_TextOpts = 3,
+	// End of data tag
+	kTraFile_EOF = -1
+};
+
+String GetTraFileErrorText(TraFileErrorType err);
+String GetTraBlockName(TraFileBlock id);
+
+typedef TypedCodeError<TraFileErrorType, GetTraFileErrorText> TraFileError;
+typedef ErrorHandle<TraFileError> HTraFileError;
+
+
+struct Translation {
+	// Game identifiers, for matching the translation file with the game
+	int GameUid;
+	String GameName;
+	// Translation dictionary in source/dest pairs
+	StringMap Dict;
+	// Localization parameters
+	int NormalFont = -1; // replacement for normal font, or -1 for default
+	int SpeechFont = -1; // replacement for speech font, or -1 for default
+	int RightToLeft = -1; // r2l text mode (0, 1), or -1 for default
+};
+
+
+// Parses translation data and tests whether it matches the given game
+HTraFileError TestTraGameID(int game_uid, const String &game_name, Stream *in);
+// Reads full translation data from the provided stream
+HTraFileError ReadTraData(Translation &tra, Stream *in);
+// Type of function that reads single trafile block and tells whether to continue reading
+typedef HTraFileError(*PfnReadTraBlock)(Stream *in, TraFileBlock block_id,
+	soff_t block_len, bool &read_next);
+// Parses tra file, passing each found block into callback; does not read any actual data itself
+HTraFileError ReadTraData(PfnReadTraBlock reader, Stream *in);
+
+} // namespace Common
+} // namespace AGS
+} // namespace AGS3
+
+#endif


Commit: 5aef4bbdf091371fe867a68d563c5735e26f52af
    https://github.com/scummvm/scummvm/commit/5aef4bbdf091371fe867a68d563c5735e26f52af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:12-07:00

Commit Message:
AGS: Don't quit if script is trying to remove invalid overlay

>From upstream 4e72ba52321c18e9b2568897de6989212d4ae7d9

Changed paths:
    engines/ags/engine/ac/dynobj/script_overlay.cpp


diff --git a/engines/ags/engine/ac/dynobj/script_overlay.cpp b/engines/ags/engine/ac/dynobj/script_overlay.cpp
index 1053a60c4d..96ff2ba59e 100644
--- a/engines/ags/engine/ac/dynobj/script_overlay.cpp
+++ b/engines/ags/engine/ac/dynobj/script_overlay.cpp
@@ -25,6 +25,7 @@
 #include "ags/engine/ac/overlay.h"
 #include "ags/engine/ac/runtime_defines.h"
 #include "ags/engine/ac/screen_overlay.h"
+#include "ags/engine/debugging/debug_log.h"
 #include "ags/globals.h"
 
 namespace AGS3 {
@@ -74,7 +75,8 @@ void ScriptOverlay::Unserialize(int index, const char *serializedData, int dataS
 void ScriptOverlay::Remove() {
 	int overlayIndex = find_overlay_of_type(overlayId);
 	if (overlayIndex < 0) {
-		quit("ScriptOverlay::Remove: overlay is not there!");
+		debug_script_warn("Overlay.Remove: overlay is invalid, could have been removed earlier.");
+		return;
 	}
 	remove_screen_overlay_index(overlayIndex);
 	overlayId = -1;


Commit: 1432b0e7fdd66a8c307cfb696e7b733c0815ea56
    https://github.com/scummvm/scummvm/commit/1432b0e7fdd66a8c307cfb696e7b733c0815ea56
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:12-07:00

Commit Message:
AGS: fixed how decrypt_text's result is null-terminated

>From upstream 059cb83c72edc6b95bdf93d1e99466ca7a233ae5

Changed paths:
    engines/ags/shared/ac/words_dictionary.cpp
    engines/ags/shared/ac/words_dictionary.h
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/game/tra_file.cpp


diff --git a/engines/ags/shared/ac/words_dictionary.cpp b/engines/ags/shared/ac/words_dictionary.cpp
index c4298dff87..1f265c75ba 100644
--- a/engines/ags/shared/ac/words_dictionary.cpp
+++ b/engines/ags/shared/ac/words_dictionary.cpp
@@ -92,10 +92,11 @@ int WordsDictionary::find_index(const char *wrem) {
 	return -1;
 }
 
-void decrypt_text(char *toenc) {
+void decrypt_text(char *toenc, size_t buf_sz) {
 	int adx = 0;
+	const char *p_end = toenc + buf_sz;
 
-	while (1) {
+	while (toenc < p_end) {
 		toenc[0] -= _G(passwencstring)[adx];
 		if (toenc[0] == 0)
 			break;
@@ -114,8 +115,8 @@ void read_string_decrypt(Stream *in, char *buf, size_t buf_sz) {
 	in->Read(buf, slen);
 	if (len > slen)
 		in->Seek(len - slen);
+	decrypt_text(buf, slen);
 	buf[slen] = 0;
-	decrypt_text(buf);
 }
 
 void read_dictionary(WordsDictionary *dict, Stream *out) {
diff --git a/engines/ags/shared/ac/words_dictionary.h b/engines/ags/shared/ac/words_dictionary.h
index 476b60729a..0d097c7f9d 100644
--- a/engines/ags/shared/ac/words_dictionary.h
+++ b/engines/ags/shared/ac/words_dictionary.h
@@ -52,7 +52,7 @@ struct WordsDictionary {
 	int   find_index(const char *);
 };
 
-extern void decrypt_text(char *toenc);
+extern void decrypt_text(char *toenc, size_t buf_sz);
 extern void read_string_decrypt(Shared::Stream *in, char *buf, size_t buf_sz);
 extern void read_dictionary(WordsDictionary *dict, Shared::Stream *in);
 
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index ffff8cfd1b..143adf9dd7 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -298,9 +298,9 @@ void ReadDialogs(DialogTopic *&dialog,
 			// which probably refered to this data used by old editor directly to edit dialogs
 			char *buffer = new char[script_text_len + 1];
 			in->Read(buffer, script_text_len);
-			buffer[script_text_len] = 0;
 			if (data_ver > kGameVersion_260)
-				decrypt_text(buffer);
+				decrypt_text(buffer, script_text_len);
+			buffer[script_text_len] = 0;
 			old_dialog_src[i] = buffer;
 			delete[] buffer;
 		} else {
@@ -360,8 +360,8 @@ void ReadDialogs(DialogTopic *&dialog,
 
 			newlen = Math::Min(newlen, sizeof(buffer) - 1);
 			in->Read(buffer, newlen);
+			decrypt_text(buffer, newlen);
 			buffer[newlen] = 0;
-			decrypt_text(buffer);
 			old_speech_lines.push_back(buffer);
 			i++;
 		}
diff --git a/engines/ags/shared/game/tra_file.cpp b/engines/ags/shared/game/tra_file.cpp
index 7237f530b0..d6880ea0b3 100644
--- a/engines/ags/shared/game/tra_file.cpp
+++ b/engines/ags/shared/game/tra_file.cpp
@@ -65,8 +65,8 @@ HTraFileError ReadTraBlock(Translation &tra, Stream *in, TraFileBlock block, sof
 		char translation[1024];
 		// Read lines until we find zero-length key & value
 		while (true) {
-			read_string_decrypt(in, original, 1024);
-			read_string_decrypt(in, translation, 1024);
+			read_string_decrypt(in, original, sizeof(original));
+			read_string_decrypt(in, translation, sizeof(translation));
 			if (!original[0] && !translation[0])
 				break;
 			tra.Dict.insert(std::make_pair(String(original), String(translation)));
@@ -76,7 +76,7 @@ HTraFileError ReadTraBlock(Translation &tra, Stream *in, TraFileBlock block, sof
 	case kTraFblk_GameID: {
 		char gamename[256];
 		tra.GameUid = in->ReadInt32();
-		read_string_decrypt(in, gamename, 256);
+		read_string_decrypt(in, gamename, sizeof(gamename));
 		tra.GameName = gamename;
 	}
 	break;


Commit: 7f6b7559be55fbf0c22742d9554c6c0e3a773a2a
    https://github.com/scummvm/scummvm/commit/7f6b7559be55fbf0c22742d9554c6c0e3a773a2a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:12-07:00

Commit Message:
AGS: Picked out data extension read/write algorithm

>From upstream f93f44c4e84cdf7814d11c56d2b8424a239982f4

Changed paths:
  A engines/ags/shared/util/data_ext.cpp
  A engines/ags/shared/util/data_ext.h
    engines/ags/module.mk


diff --git a/engines/ags/module.mk b/engines/ags/module.mk
index c7168ca467..6d327b5e91 100644
--- a/engines/ags/module.mk
+++ b/engines/ags/module.mk
@@ -74,6 +74,7 @@ MODULE_OBJS = \
 	shared/util/aligned_stream.o \
 	shared/util/buffered_stream.o \
 	shared/util/compress.o \
+	shared/util/data_ext.o \
 	shared/util/data_stream.o \
 	shared/util/directory.o \
 	shared/util/file.o \
diff --git a/engines/ags/shared/util/data_ext.cpp b/engines/ags/shared/util/data_ext.cpp
new file mode 100644
index 0000000000..1b8ca559a6
--- /dev/null
+++ b/engines/ags/shared/util/data_ext.cpp
@@ -0,0 +1,137 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ags/shared/util/data_ext.h"
+#include "ags/shared/debugging/out.h"
+#include "ags/shared/util/stream.h"
+
+namespace AGS3 {
+namespace AGS {
+namespace Shared {
+
+String GetDataExtErrorText(DataExtErrorType err) {
+	switch (err) {
+	case kDataExtErr_NoError:
+		return "No error.";
+	case kDataExtErr_UnexpectedEOF:
+		return "Unexpected end of file.";
+	case kDataExtErr_BlockDataOverlapping:
+		return "Block data overlapping.";
+	}
+	return "Unknown error.";
+}
+
+HError OpenExtBlock(Stream *in, int flags, int &block_id, String &ext_id, soff_t &block_len) {
+	//    - 1 or 4 bytes - an old-style unsigned numeric ID:
+	//               where 0 would indicate following string ID,
+	//               and -1 indicates end of the block list.
+	//    - 16 bytes - string ID of an extension (if numeric ID is 0).
+	//    - 4 or 8 bytes - length of extension data, in bytes.
+	block_id = ((flags & kDataExt_NumID32) != 0) ?
+		in->ReadInt32() :
+		in->ReadInt8();
+
+	if (block_id < 0)
+		return HError::None(); // end of list
+	if (in->EOS())
+		return new DataExtError(kDataExtErr_UnexpectedEOF);
+
+	if (block_id > 0) { // old-style block identified by a numeric id
+		block_len = ((flags & kDataExt_File64) != 0) ? in->ReadInt64() : in->ReadInt32();
+	} else { // new style block identified by a string id
+		ext_id = String::FromStreamCount(in, 16);
+		block_len = in->ReadInt64();
+	}
+	return HError::None();
+}
+
+HError ReadExtData(PfnReadExtBlock reader, int flags, Stream *in) {
+	while (!in->EOS()) {
+		// First try open the next block
+		int block_id;
+		String ext_id;
+		soff_t block_len;
+		HError err = OpenExtBlock(in, flags, block_id, ext_id, block_len);
+		if (!err)
+			return err;
+		if (block_id < 0)
+			break; // end of list
+		if (ext_id.IsEmpty()) // we may need some name for the messages
+			ext_id.Format("id:%d", block_id);
+
+		// Now call the reader function to read current block's data
+		soff_t block_end = in->GetPosition() + block_len;
+		bool read_next = true;
+		err = reader(in, block_id, ext_id, block_len, read_next);
+		if (!err)
+			return err;
+
+		// Finally test that we did not read too much or too little
+		soff_t cur_pos = in->GetPosition();
+		if (cur_pos > block_end) {
+			return new DataExtError(kDataExtErr_BlockDataOverlapping,
+				String::FromFormat("Block: '%s', expected to end at offset: %lld, finished reading at %lld.",
+					ext_id.GetCStr(), block_end, cur_pos));
+		} else if (cur_pos < block_end) {
+			Debug::Printf(kDbgMsg_Warn, "WARNING: room data blocks nonsequential, block '%s' expected to end at %lld, finished reading at %lld",
+				ext_id.GetCStr(), block_end, cur_pos);
+			in->Seek(block_end, Shared::kSeekBegin);
+		}
+
+		if (!read_next)
+			break; // reader requested a stop, do so
+	}
+	return HError::None();
+}
+
+// Generic function that saves a block and automatically adds its size into header
+void WriteExtBlock(int block, const String &ext_id, PfnWriteExtBlock writer, int flags, Stream *out) {
+	// Write block's header
+	(flags & kDataExt_NumID32) != 0 ?
+		out->WriteInt32(block) :
+		out->WriteInt8(block);
+	if (block == 0) // new-style string id
+		ext_id.WriteCount(out, 16);
+	soff_t sz_at = out->GetPosition();
+	// block size placeholder
+	((flags & kDataExt_File64) != 0) ?
+		out->WriteInt64(0) :
+		out->WriteInt32(0);
+
+	// Call writer to save actual block contents
+	writer(out);
+
+	// Now calculate the block's size...
+	soff_t end_at = out->GetPosition();
+	soff_t block_size = (end_at - sz_at) - sizeof(int64_t);
+	// ...return back and write block's size in the placeholder
+	out->Seek(sz_at, Shared::kSeekBegin);
+	((flags & kDataExt_File64) != 0) ?
+		out->WriteInt64(block_size) :
+		out->WriteInt32((int32_t)block_size);
+	// ...and get back to the end of the file
+	out->Seek(0, Shared::kSeekEnd);
+}
+
+} // namespace Common
+} // namespace AGS
+} // namespace AGS3
diff --git a/engines/ags/shared/util/data_ext.h b/engines/ags/shared/util/data_ext.h
new file mode 100644
index 0000000000..7545273c2f
--- /dev/null
+++ b/engines/ags/shared/util/data_ext.h
@@ -0,0 +1,112 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+ //=============================================================================
+ //
+ // A simple data extension format which may be useful as an ammendment to
+ // any data file in the game.
+ //
+ // Format consists of a list of "blocks", each preceded with an integer and an
+ // optional string identifier, and a size in bytes which lets a reader to skip
+ // the block completely if necessary.
+ // Because the serialization algorithm was accomodated to be shared among
+ // several existing data files, few things in the meta info may be read
+ // slightly differently depending on flags passed into the function.
+ //
+ //-----------------------------------------------------------------------------
+ //
+ // Extension format description.
+ //
+ // Each block starts with the header.
+ // * 1 or 4 bytes (depends on flags) - an old-style unsigned numeric ID :
+ //   - where 0 would indicate following string ID,
+ //   - and -1 (0xFF in case of 1 byte ID) indicates an end of the block list.
+ // * 16 bytes - fixed-len string ID of an extension (if num ID == 0).
+ // * 4 bytes - total length of the data in bytes;
+ //   - does not include the size of the header (only following data).
+ //   - new style blocks (w string ID) always use 8 bytes for a block len;
+ // * Then goes regular data.
+ //
+ // After the block is read the stream position supposed to be at
+ // (start + length of block), where "start" is a first byte of the header.
+ // If it's further - the reader bails out with error. If it's not far enough -
+ // the function logs a warning and skips remaining bytes.
+ // Blocks are read until meeting ID == -1 in the next header, which indicates
+ // the end of extension list. An EOF met earlier is considered an error.
+ //
+ //=============================================================================
+
+#ifndef AGS_SHARED_UTIL_DATA_EXT_H
+#define AGS_SHARED_UTIL_DATA_EXT_H
+
+#include "ags/shared/util/error.h"
+#include "ags/shared/util/string.h"
+
+namespace AGS3 {
+namespace AGS {
+namespace Shared {
+
+enum DataExtFlags {
+	// Size of a numeric ID in bytes
+	kDataExt_NumID8 = 0x0000, // default
+	kDataExt_NumID32 = 0x0001,
+	// 32-bit or 64-bit file offset support
+	kDataExt_File32 = 0x0000, // default
+	kDataExt_File64 = 0x0002
+};
+
+enum DataExtErrorType {
+	kDataExtErr_NoError,
+	kDataExtErr_UnexpectedEOF,
+	kDataExtErr_BlockDataOverlapping
+};
+
+String GetDataExtErrorText(DataExtErrorType err);
+typedef TypedCodeError<DataExtErrorType, GetDataExtErrorText> DataExtError;
+
+
+// Tries to opens a next block from the stream, fills in identifier and length on success
+HError OpenExtBlock(Stream *in, int flags, int &block_id, String &ext_id, soff_t &block_len);
+// Type of function that reads a single data block and tells whether to continue reading
+typedef HError(*PfnReadExtBlock)(Stream *in, int block_id, const String &ext_id,
+	soff_t block_len, bool &read_next);
+// Parses stream as a block list, passing each found block into callback;
+// does not read any actual data itself
+HError ReadExtData(PfnReadExtBlock reader, int flags, Stream *in);
+
+// Type of function that writes a single data block.
+typedef void(*PfnWriteExtBlock)(Stream *out);
+void WriteExtBlock(int block, const String &ext_id, PfnWriteExtBlock writer, int flags, Stream *out);
+// Writes a block with a new-style string id
+inline void WriteExtBlock(const String &ext_id, PfnWriteExtBlock writer, int flags, Stream *out) {
+	WriteExtBlock(0, ext_id, writer, flags, out);
+}
+// Writes a block with a old-style numeric id
+inline void WriteExtBlock(int block, PfnWriteExtBlock writer, int flags, Stream *out) {
+	WriteExtBlock(block, String(), writer, flags, out);
+}
+
+} // namespace Shared
+} // namespace AGS
+} // namespace AGS3
+
+#endif


Commit: 2d5d34809e912a976f0c608f3f895b379e904def
    https://github.com/scummvm/scummvm/commit/2d5d34809e912a976f0c608f3f895b379e904def
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:13-07:00

Commit Message:
AGS: Use shared data ext algorithm when reading/writing rooms

>From upstream b155b8585e94d8c02a0aa285dff09405e8a1946e

Changed paths:
    engines/ags/shared/game/room_file.cpp
    engines/ags/shared/game/room_file.h
    engines/ags/shared/game/room_file_base.cpp
    engines/ags/shared/util/error.h


diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index 44cb259438..fb1aa5bee6 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -33,6 +33,7 @@
 #include "ags/shared/script/cc_error.h"
 #include "ags/shared/script/cc_script.h"
 #include "ags/shared/util/compress.h"
+#include "ags/shared/util/data_ext.h"
 #include "ags/shared/util/string_utils.h"
 #include "ags/globals.h"
 
@@ -81,7 +82,7 @@ void WriteRoomObject(const RoomObjectInfo &obj, Stream *out) {
 
 
 // Main room data
-HRoomFileError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
+HError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	int bpp;
 	if (data_ver >= kRoomVersion_208)
 		bpp = in->ReadInt32();
@@ -321,30 +322,30 @@ HRoomFileError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_
 	update_polled_stuff_if_runtime();
 	loadcompressed_allegro(in, &mask, room->Palette);
 	room->HotspotMask.reset(mask);
-	return HRoomFileError::None();
+	return HError::None();
 }
 
 // Room script sources (original text)
-HRoomFileError ReadScriptBlock(char *&buf, Stream *in, RoomFileVersion data_ver) {
+HError ReadScriptBlock(char *&buf, Stream *in, RoomFileVersion data_ver) {
 	size_t len = in->ReadInt32();
 	buf = new char[len + 1];
 	in->Read(buf, len);
 	buf[len] = 0;
 	for (size_t i = 0; i < len; ++i)
 		buf[i] += _G(passwencstring)[i % 11];
-	return HRoomFileError::None();
+	return HError::None();
 }
 
 // Compiled room script
-HRoomFileError ReadCompSc3Block(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
+HError ReadCompSc3Block(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	room->CompiledScript.reset(ccScript::CreateFromStream(in));
 	if (room->CompiledScript == nullptr)
 		return new RoomFileError(kRoomFileErr_ScriptLoadFailed, _G(ccErrorString));
-	return HRoomFileError::None();
+	return HError::None();
 }
 
 // Room object names
-HRoomFileError ReadObjNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
+HError ReadObjNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	size_t name_count = in->ReadByte();
 	if (name_count != room->ObjectCount)
 		return new RoomFileError(kRoomFileErr_InconsistentData,
@@ -356,11 +357,11 @@ HRoomFileError ReadObjNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion d
 		else
 			room->Objects[i].Name.ReadCount(in, LEGACY_MAXOBJNAMELEN);
 	}
-	return HRoomFileError::None();
+	return HError::None();
 }
 
 // Room object script names
-HRoomFileError ReadObjScNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
+HError ReadObjScNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	size_t name_count = in->ReadByte();
 	if (name_count != room->ObjectCount)
 		return new RoomFileError(kRoomFileErr_InconsistentData,
@@ -372,11 +373,11 @@ HRoomFileError ReadObjScNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion
 		else
 			room->Objects[i].ScriptName.ReadCount(in, MAX_SCRIPT_NAME_LEN);
 	}
-	return HRoomFileError::None();
+	return HError::None();
 }
 
 // Secondary backgrounds
-HRoomFileError ReadAnimBgBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
+HError ReadAnimBgBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	room->BgFrameCount = in->ReadByte();
 	if (room->BgFrameCount > MAX_ROOM_BGFRAMES)
 		return new RoomFileError(kRoomFileErr_IncompatibleEngine, String::FromFormat("Too many room backgrounds (in room: %d, max: %d).", room->BgFrameCount, MAX_ROOM_BGFRAMES));
@@ -393,11 +394,11 @@ HRoomFileError ReadAnimBgBlock(RoomStruct *room, Stream *in, RoomFileVersion dat
 		load_lzw(in, &frame, room->BackgroundBPP, room->BgFrames[i].Palette);
 		room->BgFrames[i].Graphic.reset(frame);
 	}
-	return HRoomFileError::None();
+	return HError::None();
 }
 
 // Read custom properties
-HRoomFileError ReadPropertiesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
+HError ReadPropertiesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	int prop_ver = in->ReadInt32();
 	if (prop_ver != 1)
 		return new RoomFileError(kRoomFileErr_PropertiesBlockFormat, String::FromFormat("Expected version %d, got %d", 1, prop_ver));
@@ -411,10 +412,10 @@ HRoomFileError ReadPropertiesBlock(RoomStruct *room, Stream *in, RoomFileVersion
 
 	if (errors > 0)
 		return new RoomFileError(kRoomFileErr_InvalidPropertyValues);
-	return HRoomFileError::None();
+	return HError::None();
 }
 
-HRoomFileError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block, const String &ext_id,
+HError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block, const String &ext_id,
 	soff_t block_len, RoomFileVersion data_ver) {
 	//
 	// First check classic block types, identified with a numeric id
@@ -424,7 +425,7 @@ HRoomFileError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block,
 		return ReadMainBlock(room, in, data_ver);
 	case kRoomFblk_Script:
 		in->Seek(block_len); // no longer read source script text into RoomStruct
-		return HRoomFileError::None();
+		return HError::None();
 	case kRoomFblk_CompScript3:
 		return ReadCompSc3Block(room, in, data_ver);
 	case kRoomFblk_ObjectNames:
@@ -458,17 +459,22 @@ HRoomFileError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block,
 // This reader will process all blocks inside ReadRoomBlock() function,
 // and read compatible data into the given RoomStruct
 static RoomStruct *reader_room;
+static RoomFileVersion reader_data_ver;
 
-static HRoomFileError ReadRoomDataReader(Stream *in,
-		RoomFileBlock block_id, const String &ext_id,
-		soff_t block_len, RoomFileVersion data_ver, bool &read_next) {
-	return ReadRoomBlock(reader_room, in, block_id, ext_id, block_len, data_ver);
+static HError ReadRoomDataReader(Stream *in, int block_id,
+	const String &ext_id, soff_t block_len, bool &read_next) {
+	return (HError)ReadRoomBlock(reader_room, in, (RoomFileBlock)block_id, ext_id, block_len, reader_data_ver);
 }
 
 HRoomFileError ReadRoomData(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
 	room->DataVersion = data_ver;
+	reader_data_ver = data_ver;
 	reader_room = room;
-	return ReadRoomData(ReadRoomDataReader, in, data_ver);
+
+	HError err = ReadExtData(ReadRoomDataReader,
+		kDataExt_NumID8 | ((data_ver < kRoomVersion_350) ? kDataExt_File32 : kDataExt_File64), in);
+	return err ? HRoomFileError::None() :
+		new RoomFileError(kRoomFileErr_BlockListFailed, err);
 }
 
 HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos) {
@@ -602,14 +608,14 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g
 
 // Reader for ExtractScripText
 static String *reader_script;
+RoomFileVersion reader_ver;
 
-HRoomFileError ExtractScriptTextReader(Stream *in,
-		RoomFileBlock block_id, const String &ext_id, soff_t block_len,
-		RoomFileVersion data_ver, bool &read_next) {
+HError ExtractScriptTextReader(Stream *in, int block_id,
+		const String &ext_id, soff_t block_len, bool &read_next) {
 	if (block_id == kRoomFblk_Script) {
 		read_next = false;
 		char *buf = nullptr;
-		HRoomFileError err = ReadScriptBlock(buf, in, data_ver);
+		HError err = ReadScriptBlock(buf, in, reader_ver);
 		if (err) {
 			*reader_script = buf;
 			delete buf;
@@ -617,16 +623,19 @@ HRoomFileError ExtractScriptTextReader(Stream *in,
 		return err;
 	}
 	in->Seek(block_len); // skip block
-	return HRoomFileError::None();
+	return HError::None();
 }
 
 HRoomFileError ExtractScriptText(String &script, Stream *in, RoomFileVersion data_ver) {
 	// This reader would only process kRoomFblk_Script and exit as soon as one is found
 	reader_script = &script;
-	HRoomFileError err = ReadRoomData(ExtractScriptTextReader, in, data_ver);
+	reader_ver = data_ver;
+
+	HError err = ReadExtData(ExtractScriptTextReader,
+		kDataExt_NumID8 | ((data_ver < kRoomVersion_350) ? kDataExt_File32 : kDataExt_File64), in);
 	if (err && script.IsEmpty())
 		new RoomFileError(kRoomFileErr_BlockNotFound);
-	return err;
+	return err ? HRoomFileError::None() : new RoomFileError(kRoomFileErr_BlockListFailed, err);
 }
 
 void WriteInteractionScripts(const InteractionScripts *interactions, Stream *out) {
diff --git a/engines/ags/shared/game/room_file.h b/engines/ags/shared/game/room_file.h
index 7d6306900f..a52df6a59c 100644
--- a/engines/ags/shared/game/room_file.h
+++ b/engines/ags/shared/game/room_file.h
@@ -51,7 +51,7 @@ enum RoomFileErrorType {
 	kRoomFileErr_NoError,
 	kRoomFileErr_FileOpenFailed,
 	kRoomFileErr_FormatNotSupported,
-	kRoomFileErr_UnexpectedEOF,
+	kRoomFileErr_BlockListFailed,
 	kRoomFileErr_UnknownBlockType,
 	kRoomFileErr_OldBlockNotSupported,
 	kRoomFileErr_BlockDataOverlapping,
@@ -131,7 +131,7 @@ HRoomFileError ReadRoomHeader(RoomDataSource &src);
 // Opens next room block from the stream, fills in its identifier and length on success
 HRoomFileError OpenNextRoomBlock(Stream *in, RoomFileVersion data_ver, RoomFileBlock &block_id, String &ext_id, soff_t &block_len);
 // Type of function that reads single room block and tells whether to continue reading
-typedef HRoomFileError(*PfnReadRoomBlock)(Stream * in, RoomFileBlock block_id, const String & ext_id,
+typedef HError(*PfnReadRoomBlock)(Stream * in, RoomFileBlock block_id, const String & ext_id,
 	soff_t block_len, RoomFileVersion data_ver, bool &read_next);
 // Parses room file, passing each found block into callback; does not read any actual data itself
 HRoomFileError ReadRoomData(PfnReadRoomBlock reader, Stream *in, RoomFileVersion data_ver);
diff --git a/engines/ags/shared/game/room_file_base.cpp b/engines/ags/shared/game/room_file_base.cpp
index 51ab28cb3f..8796e3a003 100644
--- a/engines/ags/shared/game/room_file_base.cpp
+++ b/engines/ags/shared/game/room_file_base.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "ags/shared/game/room_file.h"
+#include "ags/shared/util/data_ext.h"
 #include "ags/shared/util/file.h"
 #include "ags/shared/debugging/out.h"
 #include "ags/globals.h"
@@ -41,14 +42,12 @@ String GetRoomFileErrorText(RoomFileErrorType err) {
 		return "Room file was not found or could not be opened.";
 	case kRoomFileErr_FormatNotSupported:
 		return "Format version not supported.";
-	case kRoomFileErr_UnexpectedEOF:
-		return "Unexpected end of file.";
+	case kRoomFileErr_BlockListFailed:
+		return "There was an error reading room data..";
 	case kRoomFileErr_UnknownBlockType:
 		return "Unknown block type.";
 	case kRoomFileErr_OldBlockNotSupported:
 		return "Block type is too old and not supported by this version of the engine.";
-	case kRoomFileErr_BlockDataOverlapping:
-		return "Block data overlapping.";
 	case kRoomFileErr_IncompatibleEngine:
 		return "This engine cannot handle requested room content.";
 	case kRoomFileErr_ScriptLoadFailed:
@@ -100,98 +99,42 @@ String GetRoomBlockName(RoomFileBlock id) {
 	return "unknown";
 }
 
-HRoomFileError OpenNextRoomBlock(Stream *in, RoomFileVersion data_ver, RoomFileBlock &block_id, String &ext_id, soff_t &block_len) {
-	// The block meta format is shared with the main game file extensions
-	//    - 1 byte - an old-style unsigned numeric ID:
-	//               where 0 would indicate following string ID,
-	//               and 0xFF indicates end of extension list.
-	//    - 16 bytes - string ID of an extension (if numeric ID is 0).
-	//    - 4 or 8 bytes - length of extension data, in bytes (size depends on format version).
-	int b = in->ReadByte();
-	if (b < 0)
-		return new RoomFileError(kRoomFileErr_UnexpectedEOF);
-
-	block_id = (RoomFileBlock)b;
-	if (block_id == kRoomFile_EOF)
-		return HRoomFileError::None(); // end of list
-
-	if (block_id > 0) { // old-style block identified by a numeric id
-		ext_id = GetRoomBlockName(block_id);
-		block_len = data_ver < kRoomVersion_350 ? in->ReadInt32() : in->ReadInt64();
-	} else { // new style block identified by a string id
-		ext_id = String::FromStreamCount(in, 16);
-		block_len = in->ReadInt64();
-	}
-	return HRoomFileError::None();
+// This reader will delegate block reading to the provided user function
+static PfnReadRoomBlock reader_reader;
+static RoomFileVersion reader_ver;
+static HError ReadRoomDataReader(Stream *in, int block_id, const String &ext_id,
+		soff_t block_len, bool &read_next) {
+	return reader_reader(in, (RoomFileBlock)block_id, ext_id, block_len, reader_ver, read_next);
 }
 
 HRoomFileError ReadRoomData(PfnReadRoomBlock reader, Stream *in, RoomFileVersion data_ver) {
-	// Read list of data blocks. The block meta format is shared with the main game file extensions now.
-	//    - 1 byte - old format block ID, 0xFF indicates end of list.
-	//    - 16 bytes - new string ID of an extension. \0 at the first byte indicates end of list.
-	//    - 4 or 8 bytes - length of extension data, in bytes (depends on format version).
-	while (true) {
-		RoomFileBlock block_id;
-		String ext_id;
-		soff_t block_len;
-		HRoomFileError err = OpenNextRoomBlock(in, data_ver, block_id, ext_id, block_len);
-		if (!err)
-			return err;
-		if (ext_id.IsEmpty())
-			break; // end of list
-
-		soff_t block_end = in->GetPosition() + block_len;
-		bool read_next = true;
-		err = reader(in, block_id, ext_id, block_len, data_ver, read_next);
-		if (!err)
-			return err;
-
-		soff_t cur_pos = in->GetPosition();
-		if (cur_pos > block_end) {
-			return new RoomFileError(kRoomFileErr_BlockDataOverlapping,
-				String::FromFormat("Block: %s, expected to end at offset: %u, finished reading at %u.",
-					ext_id.GetCStr(), block_end, cur_pos));
-		} else if (cur_pos < block_end) {
-			Debug::Printf(kDbgMsg_Warn, "WARNING: room data blocks nonsequential, block type %s expected to end at %u, finished reading at %u",
-				ext_id.GetCStr(), block_end, cur_pos);
-			in->Seek(block_end, Shared::kSeekBegin);
-		}
-
-		if (!read_next)
-			break;
-	}
-	return HRoomFileError::None();
+	reader_reader = reader;
+	reader_ver = data_ver;
+	HError err = ReadExtData(ReadRoomDataReader,
+		kDataExt_NumID8 | ((data_ver < kRoomVersion_350) ? kDataExt_File32 : kDataExt_File64), in);
+	return err ? HRoomFileError::None() : new RoomFileError(kRoomFileErr_BlockListFailed, err);
 }
 
-// Generic function that saves a block and automatically adds its size into header
-static void WriteRoomBlock(const RoomStruct *room, RoomFileBlock block, const String &ext_id, PfnWriteRoomBlock writer, Stream *out) {
-	// Write block's header
-	out->WriteByte(block);
-	if (block == kRoomFblk_None) // new-style string id
-		ext_id.WriteCount(out, 16);
-	soff_t sz_at = out->GetPosition();
-	out->WriteInt64(0); // block size placeholder
-						// Call writer to save actual block contents
-	writer(room, out);
-
-	// Now calculate the block's size...
-	soff_t end_at = out->GetPosition();
-	soff_t block_size = (end_at - sz_at) - sizeof(int64_t);
-	// ...return back and write block's size in the placeholder
-	out->Seek(sz_at, Shared::kSeekBegin);
-	out->WriteInt64(block_size);
-	// ...and get back to the end of the file
-	out->Seek(0, Shared::kSeekEnd);
+static PfnWriteRoomBlock writer_writer;
+static const RoomStruct *writer_room;
+static void WriteRoomBlockWriter(Stream *out) {
+	writer_writer(writer_room, out);
 }
 
 // Helper for new-style blocks with string id
 void WriteRoomBlock(const RoomStruct *room, const String &ext_id, PfnWriteRoomBlock writer, Stream *out) {
-	WriteRoomBlock(room, kRoomFblk_None, ext_id, writer, out);
+	writer_writer = writer;
+	writer_room = room;
+	WriteExtBlock(ext_id, WriteRoomBlockWriter,
+		kDataExt_NumID8 | kDataExt_File64, out);
 }
 
 // Helper for old-style blocks with only numeric id
 void WriteRoomBlock(const RoomStruct *room, RoomFileBlock block, PfnWriteRoomBlock writer, Stream *out) {
-	WriteRoomBlock(room, block, String(), writer, out);
+	writer_writer = writer;
+	writer_room = room;
+	WriteExtBlock(block, WriteRoomBlockWriter,
+		kDataExt_NumID8 | kDataExt_File64, out);
 }
 
 } // namespace Shared
diff --git a/engines/ags/shared/util/error.h b/engines/ags/shared/util/error.h
index 6028db6bb0..865ca61afe 100644
--- a/engines/ags/shared/util/error.h
+++ b/engines/ags/shared/util/error.h
@@ -148,6 +148,8 @@ typedef ErrorHandle<Error> HError;
 // TypedCodeError is the Error's subclass, which only purpose is to override
 // error code type in constructor and Code() getter, that may be useful if
 // you'd like to restrict code values to particular enumerator.
+// TODO: a type identifier as a part of template (string, or perhaps a int16
+// to be placed at high-bytes in Code) to be able to distinguish error group.
 template <typename CodeType, String(*GetErrorText)(CodeType)>
 class TypedCodeError : public Error {
 public:


Commit: 3c26d9c86c44e82462b512b084a8f1f8a284c1f7
    https://github.com/scummvm/scummvm/commit/3c26d9c86c44e82462b512b084a8f1f8a284c1f7
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:13-07:00

Commit Message:
AGS: use shared data ext algorithm when reading/writing MGF

>From upstream ab3fec069c1906fe545d6308dad7b88968b132a9

Changed paths:
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/game/main_game_file.h


diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 143adf9dd7..6126c29e8e 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -34,6 +34,7 @@
 #include "ags/shared/gui/gui_main.h"
 #include "ags/shared/script/cc_error.h"
 #include "ags/shared/util/aligned_stream.h"
+#include "ags/shared/util/data_ext.h"
 #include "ags/shared/util/path.h"
 #include "ags/shared/util/string_compat.h"
 #include "ags/shared/util/string_utils.h"
@@ -89,12 +90,12 @@ String GetMainGameFileErrorText(MainGameFileErrorType err) {
 		return "Format version of plugin data is not supported.";
 	case kMGFErr_PluginDataSizeTooLarge:
 		return "Plugin data size is too large.";
-	case kMGFErr_ExtUnexpectedEOF:
-		return "Unexpected end of file.";
+	case kMGFErr_ExtListFailed:
+		return "There was error reading game data extensions.";
 	case kMGFErr_ExtUnknown:
 		return "Unknown extension.";
-	case kMGFErr_ExtBlockDataOverlapping:
-		return "Block data overlapping.";
+	default:
+		break;
 	}
 	return "Unknown error.";
 }
@@ -692,8 +693,17 @@ static HGameFileError ReadExtBlock(LoadedGameEntities &ents, Stream *in, const S
 	return new MainGameFileError(kMGFErr_ExtUnknown, String::FromFormat("Type: %s", ext_id.GetCStr()));
 }
 
+static LoadedGameEntities *reader_ents;
+static GameDataVersion reader_ver;
+HError ReadGameDataReader(Stream *in, int block_id, const String &ext_id,
+		soff_t block_len, bool &read_next) {
+	return (HError)ReadExtBlock(*reader_ents, in, ext_id, block_len, reader_ver);
+}
+
 HGameFileError ReadGameData(LoadedGameEntities &ents, Stream *in, GameDataVersion data_ver) {
 	GameSetupStruct &game = ents.Game;
+	reader_ents = &ents;
+	reader_ver = data_ver;
 
 	//-------------------------------------------------------------------------
 	// The classic data section.
@@ -771,41 +781,15 @@ HGameFileError ReadGameData(LoadedGameEntities &ents, Stream *in, GameDataVersio
 	//-------------------------------------------------------------------------
 	// All the extended data, for AGS > 3.5.0.
 	//-------------------------------------------------------------------------
-	// Read list of extension blocks. The block meta format is shared with the room files.
-	//    - 1 byte - an old-style unsigned numeric ID, for compatibility with room file format:
-	//               where 0 would indicate following string ID,
-	//               and 0xFF indicates end of extension list.
-	//    - 16 bytes - string ID of an extension.
-	//    - 8 bytes - length of extension data, in bytes.
-	while (true) {
-		int b = in->ReadByte();
-		if (b < 0)
-			return new MainGameFileError(kMGFErr_ExtUnexpectedEOF);
-		if (b == 0xFF)
-			break; // end of list
-		if (b != 0) // we don't support numeric ids here
-			return new MainGameFileError(kMGFErr_ExtUnknown);
-		// Extension meta data
-		String ext_id = String::FromStreamCount(in, 16);
-		soff_t block_len = in->ReadInt64();
-		soff_t block_end = in->GetPosition() + block_len;
-		// Read game data itself
-		err = ReadExtBlock(ents, in, ext_id, block_len, data_ver);
-		if (!err)
-			return err;
-		// After each block test if the stream position is where expected
-		soff_t cur_pos = in->GetPosition();
-		if (cur_pos > block_end) {
-			return new MainGameFileError(kMGFErr_ExtBlockDataOverlapping,
-				String::FromFormat("Extension: %s, expected to end at offset: %lld, finished reading at %lld.", ext_id.GetCStr(), block_end, cur_pos));
-		} else if (cur_pos < block_end) {
-			Debug::Printf(kDbgMsg_Warn, "WARNING: game data blocks nonsequential, ext %s expected to end at %lld, finished reading at %lld",
-			              ext_id.GetCStr(), block_end, cur_pos);
-			in->Seek(block_end, Shared::kSeekBegin);
-		}
-	};
 
-	return HGameFileError::None();
+	// This reader will process all blocks inside ReadExtBlock() function,
+	// and read compatible data into the given LoadedGameEntities object.
+	auto reader = [&ents, data_ver](Stream *in, int /*block_id*/, const String &ext_id,
+		soff_t block_len, bool &read_next) {};
+
+	HError ext_err = ReadExtData(ReadGameDataReader,
+		kDataExt_NumID8 | kDataExt_File64, in);
+	return ext_err ? HGameFileError::None() : new MainGameFileError(kMGFErr_ExtListFailed, ext_err);
 }
 
 HGameFileError UpdateGameData(LoadedGameEntities &ents, GameDataVersion data_ver) {
diff --git a/engines/ags/shared/game/main_game_file.h b/engines/ags/shared/game/main_game_file.h
index e4a1903270..4e92aadb7b 100644
--- a/engines/ags/shared/game/main_game_file.h
+++ b/engines/ags/shared/game/main_game_file.h
@@ -74,9 +74,8 @@ enum MainGameFileErrorType {
 	kMGFErr_GameEntityFailed,
 	kMGFErr_PluginDataFmtNotSupported,
 	kMGFErr_PluginDataSizeTooLarge,
-	kMGFErr_ExtUnexpectedEOF,
-	kMGFErr_ExtUnknown,
-	kMGFErr_ExtBlockDataOverlapping
+	kMGFErr_ExtListFailed,
+	kMGFErr_ExtUnknown
 };
 
 String GetMainGameFileErrorText(MainGameFileErrorType err);


Commit: 7c71a16683379e6a73651aaee1569f47d3a7b343
    https://github.com/scummvm/scummvm/commit/7c71a16683379e6a73651aaee1569f47d3a7b343
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:14-07:00

Commit Message:
AGS: Use shared data ext algorithm when reading/writing translation

>From upstream e74b5ca5e45e6440f0a46a9b0fc0131c5dd6738e

Changed paths:
    engines/ags/engine/ac/translation.cpp
    engines/ags/shared/game/tra_file.cpp
    engines/ags/shared/game/tra_file.h
    engines/ags/shared/util/string_utils.cpp
    engines/ags/shared/util/string_utils.h


diff --git a/engines/ags/engine/ac/translation.cpp b/engines/ags/engine/ac/translation.cpp
index 3d839e8905..35c9bb9895 100644
--- a/engines/ags/engine/ac/translation.cpp
+++ b/engines/ags/engine/ac/translation.cpp
@@ -62,7 +62,7 @@ bool init_translation(const String &lang, const String &fallback_lang, bool quit
 	_GP(trans) = Translation();
 
 	// First test if the translation is meant for this game
-	HTraFileError err = TestTraGameID(_GP(game).uniqueid, _GP(game).gamename, in.get());
+	HError err = TestTraGameID(_GP(game).uniqueid, _GP(game).gamename, in.get());
 	if (err) {
 		// If successful, then read translation data fully
 		in.reset(_GP(AssetMgr)->OpenAsset(_G(trans_filename)));
diff --git a/engines/ags/shared/game/tra_file.cpp b/engines/ags/shared/game/tra_file.cpp
index d6880ea0b3..adc7beaa4c 100644
--- a/engines/ags/shared/game/tra_file.cpp
+++ b/engines/ags/shared/game/tra_file.cpp
@@ -23,12 +23,17 @@
 #include "ags/shared/game/tra_file.h"
 #include "ags/shared/ac/words_dictionary.h"
 #include "ags/shared/debugging/out.h"
+#include "ags/shared/util/data_ext.h"
 #include "ags/shared/util/string_compat.h"
+#include "ags/shared/util/string_utils.h"
 
 namespace AGS3 {
 namespace AGS {
 namespace Shared {
 
+const char *TRASignature = "AGSTranslation";
+
+
 String GetTraFileErrorText(TraFileErrorType err) {
 	switch (err) {
 	case kTraFileErr_NoError:
@@ -58,9 +63,19 @@ String GetTraBlockName(TraFileBlock id) {
 	return "unknown";
 }
 
-HTraFileError ReadTraBlock(Translation &tra, Stream *in, TraFileBlock block, soff_t block_len) {
+HError OpenTraFile(Stream *in) {
+	// Test the file signature
+	char sigbuf[16] = { 0 };
+	in->Read(sigbuf, 15);
+	if (ags_stricmp(TRASignature, sigbuf) != 0)
+		return new TraFileError(kTraFileErr_SignatureFailed);
+	return HError::None();
+}
+
+HError ReadTraBlock(Translation &tra, Stream *in, TraFileBlock block, soff_t block_len) {
 	switch (block) {
-	case kTraFblk_Dict: {
+	case kTraFblk_Dict:
+	{
 		char original[1024];
 		char translation[1024];
 		// Read lines until we find zero-length key & value
@@ -73,7 +88,8 @@ HTraFileError ReadTraBlock(Translation &tra, Stream *in, TraFileBlock block, sof
 		}
 	}
 	break;
-	case kTraFblk_GameID: {
+	case kTraFblk_GameID:
+	{
 		char gamename[256];
 		tra.GameUid = in->ReadInt32();
 		read_string_decrypt(in, gamename, sizeof(gamename));
@@ -89,67 +105,30 @@ HTraFileError ReadTraBlock(Translation &tra, Stream *in, TraFileBlock block, sof
 		return new TraFileError(kTraFileErr_UnknownBlockType,
 			String::FromFormat("Type: %d, known range: %d - %d.", block, kTraFblk_Dict, kTraFblk_TextOpts));
 	}
-	return HTraFileError::None();
-}
-
-HTraFileError ReadTraData(PfnReadTraBlock reader, Stream *in) {
-	// Test the file signature
-	const char *tra_sig = "AGSTranslation";
-	char sigbuf[16] = { 0 };
-	in->Read(sigbuf, 15);
-	if (ags_stricmp(tra_sig, sigbuf) != 0)
-		return new TraFileError(kTraFileErr_SignatureFailed);
-
-	while (!in->EOS()) {
-		TraFileBlock block_id = (TraFileBlock)in->ReadInt32();
-		if (block_id == kTraFile_EOF)
-			break; // end of list
-
-		soff_t block_len = in->ReadInt32();
-		soff_t block_end = in->GetPosition() + block_len;
-		String ext_id = GetTraBlockName(block_id);
-
-		bool read_next = true;
-		HTraFileError err = reader(in, block_id, block_len, read_next);
-		if (!err)
-			return err;
-
-		soff_t cur_pos = in->GetPosition();
-		if (cur_pos > block_end) {
-			return new TraFileError(kTraFileErr_BlockDataOverlapping,
-				String::FromFormat("Block: %s, expected to end at offset: %lld, finished reading at %lld.",
-					ext_id.GetCStr(), block_end, cur_pos));
-		} else if (cur_pos < block_end) {
-			Debug::Printf(kDbgMsg_Warn,
-				"WARNING: translation data blocks nonsequential, block type %s expected to end at %lld, finished reading at %lld",
-				ext_id.GetCStr(), block_end, cur_pos);
-			in->Seek(block_end, Shared::kSeekBegin);
-		}
-
-		if (!read_next)
-			break;
-	}
-	return HTraFileError::None();
+	return HError::None();
 }
 
 static Translation *reader_tra;
-
-HTraFileError TestTraGameIDReader(Stream *in, TraFileBlock block_id,
+HError TestTraGameIDReader(Stream *in, int block_id, const String &ext_id,
 		soff_t block_len, bool &read_next) {
 	if (block_id == kTraFblk_GameID) {
 		read_next = false;
-		return ReadTraBlock(*reader_tra, in, block_id, block_len);
+		return ReadTraBlock(*reader_tra, in, (TraFileBlock)block_id, block_len);
 	}
 	in->Seek(block_len); // skip block
-	return HTraFileError::None();
-}
+	return HError::None();
+};
+
+HError TestTraGameID(int game_uid, const String &game_name, Stream *in) {
+	HError err = OpenTraFile(in);
+	if (!err)
+		return err;
 
-HTraFileError TestTraGameID(int game_uid, const String &game_name, Stream *in) {
 	// This reader would only process kTraFblk_GameID and exit as soon as one is found
 	Translation tra;
 	reader_tra = &tra;
 
-	HTraFileError err = ReadTraData(TestTraGameIDReader, in);
+	err = ReadExtData(TestTraGameIDReader, kDataExt_NumID32 | kDataExt_File32, in);
 	if (!err)
 		return err;
 	// Test the identifiers, if they are not present then skip the test
@@ -157,19 +136,97 @@ HTraFileError TestTraGameID(int game_uid, const String &game_name, Stream *in) {
 		!tra.GameName.IsEmpty() && (game_name != tra.GameName))
 		return new TraFileError(kTraFileErr_GameIDMismatch,
 			String::FromFormat("The translation is designed for '%s'", tra.GameName.GetCStr()));
-	return HTraFileError::None();
+	return HError::None();
 }
 
-HTraFileError ReadTraDataReader(Stream *in, TraFileBlock block_id,
+// This reader will process all blocks inside ReadTraBlock() function,
+// and read compatible data into the given Translation object
+HError ReadTraDataReader(Stream *in, int block_id, const String &ext_id,
 		soff_t block_len, bool &read_next) {
-	return ReadTraBlock(*reader_tra, in, block_id, block_len);
+	return ReadTraBlock(*reader_tra, in, (TraFileBlock)block_id, block_len);
 }
 
-HTraFileError ReadTraData(Translation &tra, Stream *in) {
-	// This reader will process all blocks inside ReadTraBlock() function,
-	// and read compatible data into the given Translation object
+HError ReadTraData(Translation &tra, Stream *in) {
 	reader_tra = &tra;
-	return ReadTraData(ReadTraDataReader, in);
+	HError err = OpenTraFile(in);
+	if (!err)
+		return err;
+
+	return ReadExtData(ReadTraDataReader, kDataExt_NumID32 | kDataExt_File32, in);
+}
+
+// TODO: perhaps merge with encrypt/decrypt utilities
+static const char *EncryptText(std::vector<char> &en_buf, const String &s) {
+	if (en_buf.size() < s.GetLength() + 1)
+		en_buf.resize(s.GetLength() + 1);
+	strncpy(&en_buf.front(), s.GetCStr(), s.GetLength() + 1);
+	encrypt_text(&en_buf.front());
+	return &en_buf.front();
+}
+
+// TODO: perhaps merge with encrypt/decrypt utilities
+static const char *EncryptEmptyString(std::vector<char> &en_buf) {
+	en_buf[0] = 0;
+	encrypt_text(&en_buf.front());
+	return &en_buf.front();
+}
+
+void WriteGameID(const Translation &tra, Stream *out) {
+	std::vector<char> en_buf;
+	out->WriteInt32(tra.GameUid);
+	StrUtil::WriteString(EncryptText(en_buf, tra.GameName), tra.GameName.GetLength() + 1, out);
+}
+
+void WriteDict(const Translation &tra, Stream *out) {
+	std::vector<char> en_buf;
+	for (const auto &kv : tra.Dict) {
+		const String &src = kv._key;
+		const String &dst = kv._value;
+		if (!dst.IsNullOrSpace()) {
+			String unsrc = StrUtil::Unescape(src);
+			String undst = StrUtil::Unescape(dst);
+			StrUtil::WriteString(EncryptText(en_buf, unsrc), unsrc.GetLength() + 1, out);
+			StrUtil::WriteString(EncryptText(en_buf, undst), undst.GetLength() + 1, out);
+		}
+	}
+	// Write a pair of empty key/values
+	StrUtil::WriteString(EncryptEmptyString(en_buf), 1, out);
+	StrUtil::WriteString(EncryptEmptyString(en_buf), 1, out);
+}
+
+void WriteTextOpts(const Translation &tra, Stream *out) {
+	out->WriteInt32(tra.NormalFont);
+	out->WriteInt32(tra.SpeechFont);
+	out->WriteInt32(tra.RightToLeft);
+}
+
+static const Translation *writer_tra;
+static void(*writer_writer)(const Translation &tra, Stream *out);
+
+static void WriteTraBlockWriter(Stream *out) {
+	writer_writer(*writer_tra, out);
+}
+
+inline void WriteTraBlock(const Translation &tra, TraFileBlock block,
+		void(*writer)(const Translation &tra, Stream *out), Stream *out) {
+	writer_tra = &tra;
+	writer_writer = writer;
+
+	WriteExtBlock(block, WriteTraBlockWriter,
+		kDataExt_NumID32 | kDataExt_File32, out);
+}
+
+void WriteTraData(const Translation &tra, Stream *out) {
+	// Write header
+	out->Write(TRASignature, strlen(TRASignature) + 1);
+
+	// Write all blocks
+	WriteTraBlock(tra, kTraFblk_GameID, WriteGameID, out);
+	WriteTraBlock(tra, kTraFblk_Dict, WriteDict, out);
+	WriteTraBlock(tra, kTraFblk_TextOpts, WriteTextOpts, out);
+
+	// Write ending
+	out->WriteInt32(kTraFile_EOF);
 }
 
 } // namespace Shared
diff --git a/engines/ags/shared/game/tra_file.h b/engines/ags/shared/game/tra_file.h
index 4e630b8962..a649b96ddc 100644
--- a/engines/ags/shared/game/tra_file.h
+++ b/engines/ags/shared/game/tra_file.h
@@ -59,7 +59,6 @@ String GetTraFileErrorText(TraFileErrorType err);
 String GetTraBlockName(TraFileBlock id);
 
 typedef TypedCodeError<TraFileErrorType, GetTraFileErrorText> TraFileError;
-typedef ErrorHandle<TraFileError> HTraFileError;
 
 
 struct Translation {
@@ -76,14 +75,11 @@ struct Translation {
 
 
 // Parses translation data and tests whether it matches the given game
-HTraFileError TestTraGameID(int game_uid, const String &game_name, Stream *in);
+HError TestTraGameID(int game_uid, const String &game_name, Stream *in);
 // Reads full translation data from the provided stream
-HTraFileError ReadTraData(Translation &tra, Stream *in);
-// Type of function that reads single trafile block and tells whether to continue reading
-typedef HTraFileError(*PfnReadTraBlock)(Stream *in, TraFileBlock block_id,
-	soff_t block_len, bool &read_next);
-// Parses tra file, passing each found block into callback; does not read any actual data itself
-HTraFileError ReadTraData(PfnReadTraBlock reader, Stream *in);
+HError ReadTraData(Translation &tra, Stream *in);
+// Writes all translation data to the stream
+void WriteTraData(const Translation &tra, Stream *out);
 
 } // namespace Common
 } // namespace AGS
diff --git a/engines/ags/shared/util/string_utils.cpp b/engines/ags/shared/util/string_utils.cpp
index dc96cbe975..982f8353b9 100644
--- a/engines/ags/shared/util/string_utils.cpp
+++ b/engines/ags/shared/util/string_utils.cpp
@@ -67,6 +67,41 @@ StrUtil::ConversionError StrUtil::StringToInt(const String &s, int &val, int def
 	return StrUtil::kNoError;
 }
 
+String StrUtil::Unescape(const String &s) {
+	size_t at = s.FindChar('\\');
+	if (at == -1)
+		return s; // no unescaping necessary, return original string
+	char *buf = new char[s.GetLength()];
+	strncpy(buf, s.GetCStr(), at);
+	char *pb = buf + at;
+	for (const char *ptr = s.GetCStr() + at; *ptr; ++ptr) {
+		if (*ptr != '\\') {
+			*(pb++) = *ptr;
+			continue;
+		}
+
+		char next = *(++ptr);
+		switch (next) {
+		case 'a':  *(pb++) = '\a'; break;
+		case 'b':  *(pb++) = '\b'; break;
+		case 'f':  *(pb++) = '\f'; break;
+		case 'n':  *(pb++) = '\n'; break;
+		case 'r':  *(pb++) = '\r'; break;
+		case 't':  *(pb++) = '\t'; break;
+		case 'v':  *(pb++) = '\v'; break;
+		case '\\': *(pb++) = '\\'; break;
+		case '\'': *(pb++) = '\''; break;
+		case '\"': *(pb++) = '\"'; break;
+		case '\?': *(pb++) = '\?'; break;
+		default: *(pb++) = next; break;
+		}
+	}
+	*pb = 0;
+	String dst(buf);
+	delete buf;
+	return dst;
+}
+
 String StrUtil::ReadString(Stream *in) {
 	size_t len = in->ReadInt32();
 	if (len > 0)
@@ -119,6 +154,12 @@ void StrUtil::WriteString(const char *cstr, Stream *out) {
 		out->Write(cstr, len);
 }
 
+void StrUtil::WriteString(const char *cstr, size_t len, Stream *out) {
+	out->WriteInt32(len);
+	if (len > 0)
+		out->Write(cstr, len);
+}
+
 void StrUtil::ReadCStr(char *buf, Stream *in, size_t buf_limit) {
 	if (buf_limit == 0) {
 		while (in->ReadByte() > 0);
diff --git a/engines/ags/shared/util/string_utils.h b/engines/ags/shared/util/string_utils.h
index be67fc4d00..9276f56242 100644
--- a/engines/ags/shared/util/string_utils.h
+++ b/engines/ags/shared/util/string_utils.h
@@ -62,6 +62,9 @@ int             StringToInt(const String &s, int def_val = 0);
 // def_val on failure
 ConversionError StringToInt(const String &s, int &val, int def_val);
 
+// A simple unescape string implementation, unescapes '\\x' into '\x'.
+String          Unescape(const String &s);
+
 // Serialize and unserialize unterminated string prefixed with 32-bit length;
 // length is presented as 32-bit integer integer
 String          ReadString(Stream *in);
@@ -71,6 +74,7 @@ void            ReadString(String &s, Stream *in);
 void            SkipString(Stream *in);
 void            WriteString(const String &s, Stream *out);
 void            WriteString(const char *cstr, Stream *out);
+void            WriteString(const char *cstr, size_t len, Stream *out);
 
 // Serialize and unserialize string as c-string (null-terminated sequence)
 void            ReadCStr(char *buf, Stream *in, size_t buf_limit);


Commit: 1ce212d50695805a9f7e9a87a8675559205969d3
    https://github.com/scummvm/scummvm/commit/1ce212d50695805a9f7e9a87a8675559205969d3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:14-07:00

Commit Message:
AGS: removed unused function

>From upstream fc6006ca3375ed19f23c8ef1c0b060af7be273d9

Changed paths:
    engines/ags/ags.h
    engines/ags/shared/font/ttf_font_renderer.cpp


diff --git a/engines/ags/ags.h b/engines/ags/ags.h
index 4b5b972806..ddc55e7507 100644
--- a/engines/ags/ags.h
+++ b/engines/ags/ags.h
@@ -49,6 +49,10 @@ namespace AGS {
  * @brief Engine to run Adventure Game Studio games.
  */
 
+/* Synced up to upstream:
+ * "Common: removed unused function"
+ * fc6006ca3375ed19f23c8ef1c0b060af7be273d9
+ */
 #define SCREEN_WIDTH 320
 #define SCREEN_HEIGHT 200
 
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index 67fd420001..ea68d98979 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -42,13 +42,6 @@ using namespace AGS::Shared;
 // project-specific implementation
 extern bool ShouldAntiAliasText();
 
-ALFONT_FONT *tempttffnt;
-ALFONT_FONT *get_ttf_block(unsigned char *fontptr) {
-	memcpy(&tempttffnt, &fontptr[4], sizeof(tempttffnt));
-	return tempttffnt;
-}
-
-
 // ***** TTF RENDERER *****
 void TTFFontRenderer::AdjustYCoordinateForFont(int *ycoord, int fontNumber) {
 	// TTF fonts already have space at the top, so try to remove the gap


Commit: 0d600fcd9e34ca1eadab5b8289be0444bfd55c54
    https://github.com/scummvm/scummvm/commit/0d600fcd9e34ca1eadab5b8289be0444bfd55c54
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:15-07:00

Commit Message:
AGS: Fix rendering 32-bit game screens

Changed paths:
    engines/ags/engine/gfx/ali_3d_scummvm.cpp


diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index f6c727b098..a1680bb17d 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -410,8 +410,14 @@ void ScummVMRendererGraphicsDriver::RenderSpriteBatch(const ALSpriteBatch &batch
 }
 
 void ScummVMRendererGraphicsDriver::BlitToTexture() {
-	::AGS::g_vm->_screen->getSurface().blitFrom(
-		virtualScreen->GetAllegroBitmap()->getSurface());
+	const Graphics::Surface &src =
+		virtualScreen->GetAllegroBitmap()->getSurface();
+
+	// Blit the entire surface to the screen, ignoring the alphas
+	Graphics::Surface srcCopy = src;
+	srcCopy.format.aLoss = 8;
+
+	::AGS::g_vm->_screen->getSurface().blitFrom(srcCopy);
 }
 
 void ScummVMRendererGraphicsDriver::Present() {


Commit: 347885c6e8880c1afc9923f663cbb9f2d1c9afac
    https://github.com/scummvm/scummvm/commit/347885c6e8880c1afc9923f663cbb9f2d1c9afac
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:16-07:00

Commit Message:
AGS: Change quitprintf to call ScummVM error method

Changed paths:
    engines/ags/shared/ac/common.cpp


diff --git a/engines/ags/shared/ac/common.cpp b/engines/ags/shared/ac/common.cpp
index 6162eebe5b..84fd65c31d 100644
--- a/engines/ags/shared/ac/common.cpp
+++ b/engines/ags/shared/ac/common.cpp
@@ -38,7 +38,11 @@ void quitprintf(const char *fmt, ...) {
 	va_start(ap, fmt);
 	String text = String::FromFormatV(fmt, ap);
 	va_end(ap);
-	quit(text);
+
+	// WORKAROUND: In ScummVM we have to make this an error, because
+	// too many places calling it presume it doesn't return,
+	// and will throw a wobbly if does
+	error("%s", text.GetCStr());
 }
 
 } // namespace AGS3


Commit: e390466d1d55d5735ac60bd06eb1ffc868ecc915
    https://github.com/scummvm/scummvm/commit/e390466d1d55d5735ac60bd06eb1ffc868ecc915
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:16-07:00

Commit Message:
AGS: Re-convert global strings in multi_file_lib

Changed paths:
    engines/ags/shared/util/multi_file_lib.cpp


diff --git a/engines/ags/shared/util/multi_file_lib.cpp b/engines/ags/shared/util/multi_file_lib.cpp
index 629670a419..9e6d83cb03 100644
--- a/engines/ags/shared/util/multi_file_lib.cpp
+++ b/engines/ags/shared/util/multi_file_lib.cpp
@@ -30,8 +30,8 @@ namespace AGS {
 namespace Shared {
 
 namespace MFLUtil {
-const String HeadSig = "CLIB\x1a";
-const String TailSig = "CLIB\x1\x2\x3\x4SIGE";
+const char *HeadSig = "CLIB\x1a";
+const char *TailSig = "CLIB\x1\x2\x3\x4SIGE";
 
 static const size_t SingleFilePswLen = 13;
 
@@ -41,7 +41,7 @@ static const size_t V10LibFileLen = 20;
 static const size_t V10AssetFileLen = 25;
 
 static const int EncryptionRandSeed = 9338638;
-static const String EncryptionString = "My\x1\xde\x4Jibzle";
+static const char *EncryptionString = "My\x1\xde\x4Jibzle";
 
 MFLError ReadSigsAndVersion(Stream *in, MFLVersion *p_lib_version, soff_t *p_abs_offset);
 MFLError ReadSingleFileLib(AssetLibInfo &lib, Stream *in, MFLVersion lib_version);
@@ -106,39 +106,39 @@ MFLUtil::MFLError MFLUtil::ReadSigsAndVersion(Stream *in, MFLVersion *p_lib_vers
 	soff_t abs_offset = 0; // library offset in this file
 	String sig;
 	// check multifile lib signature at the beginning of file
-	sig.ReadCount(in, HeadSig.GetLength());
-	if (HeadSig.Compare(sig) != 0) {
+	sig.ReadCount(in, strlen(HeadSig));
+	if (sig.Compare(HeadSig) != 0) {
 		// signature not found, check signature at the end of file
-		in->Seek(-(soff_t)TailSig.GetLength(), kSeekEnd);
+		in->Seek(-(soff_t)strlen(TailSig), kSeekEnd);
 		// by definition, tail marks the max absolute offset value
 		auto tail_abs_offset = in->GetPosition();
-		sig.ReadCount(in, TailSig.GetLength());
+		sig.ReadCount(in, strlen(TailSig));
 		// signature not found, return error code
-		if (TailSig.Compare(sig) != 0)
+		if (sig.Compare(TailSig) != 0)
 			return kMFLErrNoLibSig;
 
 		// it's an appended-to-end-of-exe thing;
 		// now we need to read multifile lib offset value, but we do not know
 		// if its 32-bit or 64-bit yet, so we'll have to test both
-		in->Seek(-(soff_t)TailSig.GetLength() - sizeof(int64_t), kSeekEnd);
+		in->Seek(-(soff_t)strlen(TailSig) - sizeof(int64_t), kSeekEnd);
 		abs_offset = in->ReadInt64();
 		in->Seek(-(soff_t)sizeof(int32_t), kSeekCurrent);
 		soff_t abs_offset_32 = in->ReadInt32();
 
 		// test for header signature again, with 64-bit and 32-bit offsets if necessary
-		if (abs_offset > 0 && abs_offset < (soff_t)(tail_abs_offset - HeadSig.GetLength())) {
+		if (abs_offset > 0 && abs_offset < (soff_t)(tail_abs_offset - strlen(HeadSig))) {
 			in->Seek(abs_offset, kSeekBegin);
-			sig.ReadCount(in, HeadSig.GetLength());
+			sig.ReadCount(in, strlen(HeadSig));
 		}
 
 		// try again with 32-bit offset
-		if (HeadSig.Compare(sig) != 0) {
+		if (sig.Compare(HeadSig) != 0) {
 			abs_offset = abs_offset_32;
-			if (abs_offset > 0 && abs_offset < (soff_t)(tail_abs_offset - HeadSig.GetLength())) {
+			if (abs_offset > 0 && abs_offset < (soff_t)(tail_abs_offset - strlen(HeadSig))) {
 				in->Seek(abs_offset, kSeekBegin);
-				sig.ReadCount(in, HeadSig.GetLength());
+				sig.ReadCount(in, strlen(HeadSig));
 			}
-			if (HeadSig.Compare(sig) != 0) {
+			if (sig.Compare(HeadSig) != 0) {
 				// nope, no luck, bad / unknown format
 				return kMFLErrNoLibSig;
 			}
@@ -328,7 +328,7 @@ MFLUtil::MFLError MFLUtil::ReadV30(AssetLibInfo &lib, Stream *in, MFLVersion /*
 }
 
 void MFLUtil::WriteHeader(const AssetLibInfo &lib, MFLVersion lib_version, int lib_index, Stream *out) {
-	out->Write(MFLUtil::HeadSig.GetCStr(), MFLUtil::HeadSig.GetLength());
+	out->Write(HeadSig, strlen(HeadSig));
 	out->WriteByte(lib_version);
 	out->WriteByte(lib_index);   // file number
 
@@ -361,7 +361,7 @@ void MFLUtil::WriteEnder(soff_t lib_offset, MFLVersion lib_index, Stream *out) {
 		out->WriteInt32((int32_t)lib_offset);
 	else
 		out->WriteInt64(lib_offset);
-	out->Write(TailSig.GetCStr(), TailSig.GetLength());
+	out->Write(TailSig, strlen(TailSig));
 }
 
 void MFLUtil::DecryptText(char *text) {


Commit: 3a60a8db2f6c231594d8b6ffa42442b9377c9a92
    https://github.com/scummvm/scummvm/commit/3a60a8db2f6c231594d8b6ffa42442b9377c9a92
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:17-07:00

Commit Message:
AGS: Convert other global strings to const char *

Changed paths:
    engines/ags/engine/ac/file.cpp
    engines/ags/engine/ac/path_helper.h
    engines/ags/engine/game/savegame.cpp
    engines/ags/engine/game/savegame.h
    engines/ags/engine/main/config.cpp


diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index b22fd4c951..221bf97184 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -202,11 +202,11 @@ int File_GetPosition(sc_File *fil) {
 //=============================================================================
 
 
-const String GameInstallRootToken = "$INSTALLDIR$";
-const String UserSavedgamesRootToken = "$MYDOCS$";
-const String GameSavedgamesDirToken = "$SAVEGAMEDIR$";
-const String GameDataDirToken = "$APPDATADIR$";
-const String UserConfigFileToken = "$CONFIGFILE$";
+const char *GameInstallRootToken = "$INSTALLDIR$";
+const char *UserSavedgamesRootToken = "$MYDOCS$";
+const char *GameSavedgamesDirToken = "$SAVEGAMEDIR$";
+const char *GameDataDirToken = "$APPDATADIR$";
+const char *UserConfigFileToken = "$CONFIGFILE$";
 
 void FixupFilename(char *filename) {
 	const char *illegal = _G(platform)->GetIllegalFileChars();
@@ -306,10 +306,10 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 			return false;
 		}
 		parent_dir = FSLocation(_GP(ResPaths).DataDir);
-		child_path = sc_path.Mid(GameInstallRootToken.GetLength());
+		child_path = sc_path.Mid(strlen(GameInstallRootToken));
 	} else if (sc_path.CompareLeft(GameSavedgamesDirToken) == 0) {
 		parent_dir = get_save_game_directory();
-		child_path = sc_path.Mid(strlen(GameSavedgamesDirToken.GetCStr()));
+		child_path = sc_path.Mid(strlen(GameSavedgamesDirToken));
 #if AGS_PLATFORM_SCUMMVM
 		// Remap "agsgame.*"
 		const char *agsSavePrefix = "/agssave.";
@@ -328,7 +328,7 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
 #endif
 	} else if (sc_path.CompareLeft(GameDataDirToken) == 0) {
 		parent_dir = GetGameAppDataDir();
-		child_path = sc_path.Mid(GameDataDirToken.GetLength());
+		child_path = sc_path.Mid(strlen(GameDataDirToken));
 	} else {
 		child_path = sc_path;
 
diff --git a/engines/ags/engine/ac/path_helper.h b/engines/ags/engine/ac/path_helper.h
index 907c023d43..04e4d773bd 100644
--- a/engines/ags/engine/ac/path_helper.h
+++ b/engines/ags/engine/ac/path_helper.h
@@ -40,10 +40,10 @@ namespace AGS3 {
 using AGS::Shared::String;
 
 // Filepath tokens, which are replaced by platform-specific directory names
-extern const String UserSavedgamesRootToken;
-extern const String GameSavedgamesDirToken;
-extern const String GameDataDirToken;
-extern const String DefaultConfigFileName;
+extern const char *UserSavedgamesRootToken;
+extern const char *GameSavedgamesDirToken;
+extern const char *GameDataDirToken;
+extern const char *DefaultConfigFileName;
 
 // Subsitutes illegal characters with '_'. This function uses illegal chars array
 // specific to current platform.
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index aeefb16a02..fbb81ebe93 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -77,8 +77,8 @@ HSaveError restore_game_data(Stream *in, SavegameVersion svg_version, const Pres
 namespace AGS {
 namespace Engine {
 
-const String SavegameSource::LegacySignature = "Adventure Game Studio saved game";
-const String SavegameSource::Signature = "Adventure Game Studio saved game v2";
+const char *SavegameSource::LegacySignature = "Adventure Game Studio saved game";
+const char *SavegameSource::Signature = "Adventure Game Studio saved game v2";
 
 SavegameSource::SavegameSource()
 	: Version(kSvgVersion_Undefined) {
@@ -271,12 +271,12 @@ HSaveError OpenSavegameBase(const String &filename, SavegameSource *src, Savegam
 	// Check saved game signature
 	bool is_new_save = false;
 	size_t pre_sig_pos = in->GetPosition();
-	String svg_sig = String::FromStreamCount(in.get(), SavegameSource::Signature.GetLength());
+	String svg_sig = String::FromStreamCount(in.get(), strlen(SavegameSource::Signature));
 	if (svg_sig.Compare(SavegameSource::Signature) == 0) {
 		is_new_save = true;
 	} else {
 		in->Seek(pre_sig_pos, kSeekBegin);
-		svg_sig = String::FromStreamCount(in.get(), SavegameSource::LegacySignature.GetLength());
+		svg_sig = String::FromStreamCount(in.get(), strlen(SavegameSource::LegacySignature));
 		if (svg_sig.Compare(SavegameSource::LegacySignature) != 0)
 			return new SavegameError(kSvgErr_SignatureFailed);
 	}
@@ -722,7 +722,7 @@ Stream *StartSavegame(const String &filename, const String &user_text, const Bit
 	vistaHeader.WriteToFile(out);
 
 	// Savegame signature
-	out->Write(SavegameSource::Signature.GetCStr(), SavegameSource::Signature.GetLength());
+	out->Write(SavegameSource::Signature, strlen(SavegameSource::Signature));
 
 	// CHECKME: what is this plugin hook suppose to mean, and if it is called here correctly
 	pl_run_plugin_hooks(AGSE_PRESAVEGAME, 0);
diff --git a/engines/ags/engine/game/savegame.h b/engines/ags/engine/game/savegame.h
index 8d0635a060..2b7703151e 100644
--- a/engines/ags/engine/game/savegame.h
+++ b/engines/ags/engine/game/savegame.h
@@ -107,9 +107,9 @@ typedef std::unique_ptr<Stream> UStream;
 // SavegameSource defines a successfully opened savegame stream
 struct SavegameSource {
 	// Signature of the current savegame format
-	static const String Signature;
+	static const char *Signature;
 	// Signature of the legacy savegame format
-	static const String LegacySignature;
+	static const char *LegacySignature;
 
 	// Name of the savefile
 	String              Filename;
diff --git a/engines/ags/engine/main/config.cpp b/engines/ags/engine/main/config.cpp
index 933656b381..0c4c4be333 100644
--- a/engines/ags/engine/main/config.cpp
+++ b/engines/ags/engine/main/config.cpp
@@ -50,7 +50,7 @@ using namespace AGS::Shared;
 using namespace AGS::Engine;
 
 // Filename of the default config file, the one found in the game installation
-const String DefaultConfigFileName = "acsetup.cfg";
+const char *DefaultConfigFileName = "acsetup.cfg";
 
 bool INIreaditem(const ConfigTree &cfg, const String &sectn, const String &item, String &value) {
 	ConfigNode sec_it = cfg.find(sectn);


Commit: 2a11ab182423e665140f8f26ce653fb3adacc671
    https://github.com/scummvm/scummvm/commit/2a11ab182423e665140f8f26ce653fb3adacc671
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:09:17-07:00

Commit Message:
AGS: Re-introduce fix for Fatman intro crash

Changed paths:
    engines/ags/engine/ac/character.cpp


diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 040bd67f7a..4ed75fba54 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -2385,7 +2385,12 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 		if ((speakingChar->view < 0) ||
 		        (speakingChar->loop >= _G(views)[speakingChar->view].numLoops) ||
 		        (_G(views)[speakingChar->view].loops[speakingChar->loop].numFrames < 1)) {
+#if AGS_PLATFORM_SCUMMVM
+			// WORKAROUND: Fix crash in Fatman intro by ignoring invalid speeches
+			return;
+#else
 			quitprintf("Unable to display speech because the character %s has an invalid view frame (View %d, loop %d, frame %d)", speakingChar->scrname, speakingChar->view + 1, speakingChar->loop, speakingChar->frame);
+#endif
 		}
 
 		_G(our_eip) = 1504;
@@ -2626,7 +2631,12 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
 			if (speakingChar->on && // don't bother checking if character is not visible (also fixes 'Trilby's Notes' legacy game)
 			        ((speakingChar->loop >= _G(views)[speakingChar->view].numLoops) ||
 			         (_G(views)[speakingChar->view].loops[speakingChar->loop].numFrames < 1))) {
+#if AGS_PLATFORM_SCUMMVM
+				// WORKAROUND: Fix crash in Fatman intro by ignoring invalid speeches
+				return;
+#else
 				quitprintf("!Unable to display speech because the character %s has an invalid speech view (View %d, loop %d, frame %d)", speakingChar->scrname, speakingChar->view + 1, speakingChar->loop, speakingChar->frame);
+#endif
 			}
 
 			// set up the speed of the first frame


Commit: 14a84067190850984d06770b092569c9ca5377e4
    https://github.com/scummvm/scummvm/commit/14a84067190850984d06770b092569c9ca5377e4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:20:41-07:00

Commit Message:
AGS: Fix GUI sprite renderings

Changed paths:
    engines/ags/engine/gfx/blender.cpp


diff --git a/engines/ags/engine/gfx/blender.cpp b/engines/ags/engine/gfx/blender.cpp
index e5d6af98be..c9c08e3bcc 100644
--- a/engines/ags/engine/gfx/blender.cpp
+++ b/engines/ags/engine/gfx/blender.cpp
@@ -233,21 +233,22 @@ unsigned long _argb2rgb_blender(unsigned long src_col, unsigned long dst_col, un
 	return res | g;
 }
 
-void set_additive_alpha_blender() {
-	set_blender_mode(nullptr, nullptr, _additive_alpha_copysrc_blender, 0, 0, 0, 0);
+// sets the alpha channel to opaque. used when drawing a non-alpha sprite onto an alpha-sprite
+unsigned long _opaque_alpha_blender(unsigned long x, unsigned long y, unsigned long n) {
+	return x | 0xff000000;
 }
 
-void set_argb2argb_blender(int alpha) {
-	set_blender_mode(nullptr, nullptr, _argb2argb_blender, 0, 0, 0, alpha);
+
+void set_additive_alpha_blender() {
+	set_blender_mode(kAdditiveBlenderMode, 0, 0, 0, 0);
 }
 
-// sets the alpha channel to opaque. used when drawing a non-alpha sprite onto an alpha-sprite
-unsigned long _opaque_alpha_blender(unsigned long x, unsigned long y, unsigned long n) {
-	return x | 0xff000000;
+void set_argb2argb_blender(int alpha) {
+	set_blender_mode(kArgbToArgbBlender, 0, 0, 0, alpha);
 }
 
 void set_opaque_alpha_blender() {
-	set_blender_mode(nullptr, nullptr, _opaque_alpha_blender, 0, 0, 0, 0);
+	set_blender_mode(kOpaqueBlenderMode, 0, 0, 0, 0);
 }
 
 } // namespace AGS3


Commit: 31dc015df5bef87cb499ac75deca88399402e35a
    https://github.com/scummvm/scummvm/commit/31dc015df5bef87cb499ac75deca88399402e35a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2021-06-13T21:42:08-07:00

Commit Message:
AGS: Fix gcc warnings

Changed paths:
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/game/room_file_base.cpp
    engines/ags/shared/game/tra_file.cpp
    engines/ags/shared/util/memory_stream.cpp
    engines/ags/shared/util/string_utils.cpp


diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 6126c29e8e..ab7db262bd 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -693,6 +693,8 @@ static HGameFileError ReadExtBlock(LoadedGameEntities &ents, Stream *in, const S
 	return new MainGameFileError(kMGFErr_ExtUnknown, String::FromFormat("Type: %s", ext_id.GetCStr()));
 }
 
+// This reader will process all blocks inside ReadExtBlock() function,
+// and read compatible data into the given LoadedGameEntities object.
 static LoadedGameEntities *reader_ents;
 static GameDataVersion reader_ver;
 HError ReadGameDataReader(Stream *in, int block_id, const String &ext_id,
@@ -782,11 +784,6 @@ HGameFileError ReadGameData(LoadedGameEntities &ents, Stream *in, GameDataVersio
 	// All the extended data, for AGS > 3.5.0.
 	//-------------------------------------------------------------------------
 
-	// This reader will process all blocks inside ReadExtBlock() function,
-	// and read compatible data into the given LoadedGameEntities object.
-	auto reader = [&ents, data_ver](Stream *in, int /*block_id*/, const String &ext_id,
-		soff_t block_len, bool &read_next) {};
-
 	HError ext_err = ReadExtData(ReadGameDataReader,
 		kDataExt_NumID8 | kDataExt_File64, in);
 	return ext_err ? HGameFileError::None() : new MainGameFileError(kMGFErr_ExtListFailed, ext_err);
diff --git a/engines/ags/shared/game/room_file_base.cpp b/engines/ags/shared/game/room_file_base.cpp
index 8796e3a003..b854577d12 100644
--- a/engines/ags/shared/game/room_file_base.cpp
+++ b/engines/ags/shared/game/room_file_base.cpp
@@ -60,6 +60,8 @@ String GetRoomFileErrorText(RoomFileErrorType err) {
 		return "Errors encountered when reading custom properties.";
 	case kRoomFileErr_BlockNotFound:
 		return "Required block was not found.";
+	default:
+		break;
 	}
 	return "Unknown error.";
 }
diff --git a/engines/ags/shared/game/tra_file.cpp b/engines/ags/shared/game/tra_file.cpp
index adc7beaa4c..964bd96a60 100644
--- a/engines/ags/shared/game/tra_file.cpp
+++ b/engines/ags/shared/game/tra_file.cpp
@@ -59,6 +59,7 @@ String GetTraBlockName(TraFileBlock id) {
 	case kTraFblk_Dict: return "Dictionary";
 	case kTraFblk_GameID: return "GameID";
 	case kTraFblk_TextOpts: return "TextOpts";
+	default: break;
 	}
 	return "unknown";
 }
@@ -117,7 +118,7 @@ HError TestTraGameIDReader(Stream *in, int block_id, const String &ext_id,
 	}
 	in->Seek(block_len); // skip block
 	return HError::None();
-};
+}
 
 HError TestTraGameID(int game_uid, const String &game_name, Stream *in) {
 	HError err = OpenTraFile(in);
@@ -133,7 +134,7 @@ HError TestTraGameID(int game_uid, const String &game_name, Stream *in) {
 		return err;
 	// Test the identifiers, if they are not present then skip the test
 	if ((tra.GameUid != 0 && (game_uid != tra.GameUid)) ||
-		!tra.GameName.IsEmpty() && (game_name != tra.GameName))
+		(!tra.GameName.IsEmpty() && (game_name != tra.GameName)))
 		return new TraFileError(kTraFileErr_GameIDMismatch,
 			String::FromFormat("The translation is designed for '%s'", tra.GameName.GetCStr()));
 	return HError::None();
diff --git a/engines/ags/shared/util/memory_stream.cpp b/engines/ags/shared/util/memory_stream.cpp
index 5931e1e243..f0134950db 100644
--- a/engines/ags/shared/util/memory_stream.cpp
+++ b/engines/ags/shared/util/memory_stream.cpp
@@ -72,7 +72,7 @@ bool MemoryStream::IsValid() const {
 }
 
 bool MemoryStream::EOS() const {
-	return _pos >= _len;
+	return _pos >= (soff_t)_len;
 }
 
 soff_t MemoryStream::GetLength() const {
diff --git a/engines/ags/shared/util/string_utils.cpp b/engines/ags/shared/util/string_utils.cpp
index 982f8353b9..0043049013 100644
--- a/engines/ags/shared/util/string_utils.cpp
+++ b/engines/ags/shared/util/string_utils.cpp
@@ -69,7 +69,7 @@ StrUtil::ConversionError StrUtil::StringToInt(const String &s, int &val, int def
 
 String StrUtil::Unescape(const String &s) {
 	size_t at = s.FindChar('\\');
-	if (at == -1)
+	if (at == String::npos)
 		return s; // no unescaping necessary, return original string
 	char *buf = new char[s.GetLength()];
 	strncpy(buf, s.GetCStr(), at);




More information about the Scummvm-git-logs mailing list